Commit Graph

353 Commits

Author SHA1 Message Date
Régis Brid
24dfd6aebe
feat: enhance device.status with system health sections (#249)
Some checks are pending
Build and Test / release (push) Blocked by required conditions
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
Adds richer `device.status` sections while preserving the existing command surface and legacy status fields.

- adds an injected `IDeviceStatusProvider` abstraction for platform-specific status collection
- adds Windows OS, CPU, memory, disk, and battery status collection
- supports `sections[]` filtering with unknown-section validation
- preserves legacy battery, thermal, storage, network, and uptime fields for compatibility
- adds tests for filtering, failure isolation, legacy compatibility, and provider disposal behavior

Closes #240.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-01 11:54:51 -07:00
Régis Brid
e0c40985a7
feat: add Windows node text-to-speech (#253)
Adds a focused Windows node text-to-speech capability as the first stable voice-support primitive.

- adds the shared `tts.speak` capability and MCP/gateway documentation
- wires Windows and ElevenLabs TTS behind opt-in tray settings
- protects the ElevenLabs API key with DPAPI
- adds shared and tray tests for capability behavior, settings, and ElevenLabs requests

This lands the focused TTS foundation from the broader Voice Mode discussion in #120 so remaining voice UX/STT/repeater work can build on top in smaller follow-up PRs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-01 11:31:58 -07:00
github-actions[bot]
758c881f9d
fix: McpHttpServer and tests for Linux HttpListener behavior (#238)
Three McpHttpServerTests were failing on Linux:

1. Post_WithLocalhostHost_Accepted — HttpListener on Linux rejects
   requests with Host: localhost when only http://127.0.0.1:port/ is
   registered as a prefix (404 before reaching application code). Fix:
   also register http://localhost:port/ so clients connecting via the
   hostname form are served.

2. Post_WithRebindHost_RejectedWithForbidden — With the dual-prefix
   registration, Host: evil.com still doesn't match, but Linux returns
   404 (HttpListener filter) rather than 403 (application code). Both
   are valid rejections; relax assertion to NotEqual(OK).

3. Post_OversizedBody_RejectedWithRequestTooLarge — When the server
   sends 413 and closes the connection before the client finishes
   uploading 5 MiB, Linux surfaces a broken-pipe SocketException rather
   than letting the client see the response status. Catch the
   SocketException path as an equivalent rejection outcome.

All 15 McpHttpServer tests now pass on Linux (967 pass, 20 skip).

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-05-01 10:39:40 -07:00
github-actions[bot]
1773cc7ef1
perf(mcp): eliminate LINQ and ToArray() allocations in McpToolBridge (#243)
- Remove System.Linq import; replace FirstOrDefault with foreach loop
  in HandleToolsCallAsync — avoids delegate allocation on every tool call
- Replace ms.ToArray() with ms.GetBuffer() + slice in WriteResult and
  WriteError — avoids copying the byte array before UTF-8 decoding

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-05-01 10:20:36 -07:00
AlexAlves87
72ffc78b62
refactor(tray): remove two unused tray menu helpers (~240 lines) (#251)
* refactor(tray): remove unused BuildTrayMenuFlyout

Method was never called. Active tray menu is driven by
BuildTrayMenuPopup(TrayMenuWindow) via ShowTrayMenuPopup().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tray): remove legacy unused BuildTrayMenu

Method was explicitly marked "for reference" in a comment but never
called. BuildTrayMenuPopup(TrayMenuWindow) is the active implementation.
Removes the comment and the entire method body.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: AlexAlves87 <alexalves87@github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 10:15:24 -07:00
github-actions[bot]
61ef7d14c0
test: add SshTunnelCommandLine, ExecApprovalV2Result, and McpToolBridge coverage gaps (#245)
- SshTunnelCommandLine: 7 new tests covering CanForwardBrowserProxyPort
  boundary values and BuildArguments whitespace trimming
- ExecApprovalV2Result: test ToString() includes code and reason
- McpToolBridge: test custom serverName/serverVersion via constructor;
  test that null arguments value is accepted (not just missing arguments)

All tests pass (Shared + Tray).

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-05-01 09:54:46 -07:00
github-actions[bot]
dc640eef32
fix(security): block dangerous stem+wildcard allow patterns in execApprovals.set (#255)
ValidateExecApprovalRules previously checked for dangerous fragments that end
with a trailing space (e.g. "rm ") but missed the case where the wildcard
character replaces the space — e.g. "rm*" passes the "rm " fragment check yet
matches "rm -rf /" via the ^rm.*$ regex, effectively bypassing the intended
block.

Fix: for each dangerous fragment that has trailing whitespace, also reject
patterns containing the trimmed stem followed directly by * or ?.

Before:
  { "pattern": "rm*", "action": "allow" }  → accepted, allows "rm -rf /"
  { "pattern": "del*", "action": "allow" } → accepted, allows "del /s /q C:\\"

After:
  { "pattern": "rm*", "action": "allow" }  → rejected ("Dangerous allow rule…")
  { "pattern": "del*", "action": "allow" } → rejected

Adds 7 InlineData regression tests covering: rm*, rm?, del*, del?,
remove-item*, shutdown*, net*.

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-05-01 09:54:41 -07:00
github-actions[bot]
4207163091
fix(security): catch all-wildcard allow patterns in exec approval policy (#247)
ValidateExecApprovalRules rejected single '*' but missed patterns like
'**', '***', '?', '? *', '* ?' that also match any command string.

An agent that can call system.execApprovals.set could bypass the
broad-allow restriction by submitting '**' as an allow pattern:
  {"rules": [{"pattern": "**", "action": "allow"}], "baseHash": "..."}

The glob-to-regex translation turns '**' into '^.*.*$', which matches
every command, exactly like '*' does.

Fix: strip all wildcard chars ('*', '?') and whitespace from the
normalised pattern before checking. If nothing remains the pattern is
an all-wildcard glob and is rejected as broad.  The explicit shell-
prefix checks (powershell *, pwsh *, cmd *, cmd.exe *) are preserved
for patterns that contain meaningful content but are still too broad.

Tests: add **,  ***, ?, '? *', '* ?' to ExecApprovalsSet_RejectsUnsafeAllowRules.

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-05-01 09:54:36 -07:00
Scott Hanselman
70b8ee6fb8 test: isolate tray onboarding settings
Prevent tray onboarding tests from reading real user settings by allowing SettingsManager to use an explicit settings directory and using temp settings in onboarding tests. Document the isolation rule for future agents.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-01 09:49:14 -07:00
Chris Anderson
3b8793db37
feat: winnode CLI for invoking node commands over local MCP (#250)
* feat: winnode CLI for invoking node commands over local MCP

Mirrors `openclaw nodes invoke`'s flag surface but routes to the local
tray's MCP HTTP server (default http://127.0.0.1:8765/) instead of the
gateway. `--node` and `--idempotency-key` are accepted for paste-from-
gateway parity and ignored.

Ships skill.md alongside winnode.exe documenting every supported
command, argument schema, and the A2UI v0.8 JSONL grammar for agent use.

Tests: 62 cases, 100% line/branch on CliRunner via in-process unit tests
plus a loopback HttpListener fake that exercises the full HTTP path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(test): gate MCP readiness on token-bearing client

InitializeAsync would return ready as soon as `GET /` returned 200, even
if `mcp-token.txt` had not been read yet. Against a tray binary built
before the auth-before-dispatch hardening (where `GET /` answers 200
without auth), this raced ahead and handed back a tokenless `Client` —
every subsequent POST then 401'd. Restructure the loop to require both
the token-on-disk and a 200 from a token-bearing GET before declaring
ready.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(winnode): auto-load MCP bearer token

The CLI now sends `Authorization: Bearer <token>` on every MCP request,
without the user having to plumb the token themselves. Resolution chain
mirrors the per-tool secret convention (gh, az, anthropic):

  1. `--mcp-token <literal>` flag
  2. `OPENCLAW_MCP_TOKEN` env var (literal)
  3. `mcp-token.txt` under `$OPENCLAW_TRAY_DATA_DIR` if set, else
     `%APPDATA%\OpenClawTray\` — the same location SettingsManager
     points the tray at, so a sandboxed tray is found automatically.

When the token comes from disk, run `McpAuthToken.VerifyAcl` (the same
hygiene check `NodeService.StartMcpServer` runs at startup) and route
any owner/DACL warning to stderr so the user knows to rotate. `--verbose`
reports the resolved auth source without echoing the secret value.

Tests redirect via `OPENCLAW_TRAY_DATA_DIR` to a temp sandbox dir so they
don't pick up the developer machine's real tray token.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(winnode): apply 19 review findings (F-01..F-21)

Hardens the winnode CLI against the threat model in
C:/temp/winnode-cli-review-2026-04-30/01-findings.md. F-15 (port-0 nit)
was approved as no-action; F-17 was a positive observation.

- F-01/F-09: validate --mcp-url; refuse auto-loaded token off-loopback
- F-02: explicit SocketsHttpHandler with AllowAutoRedirect=false
- F-03: cap response body at 16 MiB with explicit overflow message
- F-04: warn unconditionally when --mcp-token is used (process-listing leak)
- F-05: warn unconditionally when --idempotency-key is supplied
- F-06: TokenLooksValid ASCII-printable check; ignore corrupt tokens
- F-07: don't echo full token-file path in --verbose
- F-08: canonicalize OPENCLAW_TRAY_DATA_DIR; reject symlink redirect
- F-10: RunAsyncTests is now IDisposable (cleans up sandbox dir)
- F-11: SkillMdDriftTests + REGENERATE-ME header in skill.md;
        McpToolBridge.KnownCommands exposes the canonical command set;
        skill.md re-synced with live capability surface
- F-12: --params @<path> loads JSON object from disk
- F-13: Token_file_with_wide_acl_emits_warn (Windows-only, gracefully
        skips when SetAccessControl is denied by hardened CI)
- F-14: BuildToolsCallBody returns (byte[], int) consumed by
        ByteArrayContent without a string round-trip
- F-16+F-21: SanitizeForStderr strips control chars, redacts ≥32-char
        base64url runs, caps at 4 KiB, default-quiet first-line-only,
        full sanitized body under --verbose
- F-18: --invoke-timeout capped at 600000 ms; long arithmetic on the
        +5000 buffer; out-of-range exits 2
- F-19: --mcp-port and OPENCLAW_MCP_PORT bounded [1, 65535]; env-var
        out-of-range falls back to default with a verbose warning
- F-20: distinguish missing/empty/unreadable/loaded token-file states;
        unreadable exits 1 with a diagnostic before any HTTP traffic

Tests: 23 added (115/115 pass). All other suites stay green
(Shared 1046/1066, Tray 245/245, Integration 18/18, UI 62/62).
WinNode CLI line coverage: 91.6% (434/474 in Program.cs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 09:27:50 -07:00
Mike Harsh
1433349d10
feat(tray): add onboarding wizard updates (#241)
* Snap Reactor framework as OpenClawTray.Infrastructure

- Copy microsoft/microsoft-ui-reactor src/Reactor/ (249 C# files, 12 modules)
- Rename namespace Microsoft.UI.Reactor -> OpenClawTray.Infrastructure
- Create OpenClawTray.Infrastructure.csproj (net10.0, WinAppSDK 1.8)
- Add ProjectReference from OpenClaw.Tray.WinUI
- Add project to moltbot-windows-hub.slnx
- Fix C# 14 field keyword conflict in ValidationContext.cs
- Exclude ReactorApplication.xaml (library mode, host app owns Application)
- Update global.json rollForward to latestMajor
- Full solution builds clean (0 errors)

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

* Implement OnboardingWindow host with Reactor pages

- OnboardingWindow.cs: WindowEx host with ReactorHostControl, Mica backdrop, 720x752
- OnboardingApp.cs: Root Reactor component with UseNavigation, step indicator, back/next
- OnboardingState.cs: Shared state with mode-dependent page order (matches macOS flow)
- WelcomePage.cs: Page 0 - welcome title + security notice card
- ConnectionPage.cs: Page 1 - local/remote/later gateway selection
- ReadyPage.cs: Page 9 - feature summary with emoji rows
- Placeholder stubs for Wizard/Permissions/Chat pages (Phase 3)
- Full solution builds clean via build.ps1

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

* Wire first-run detection and tray menu to OnboardingWindow

- First-run: ShowOnboardingAsync() replaces ShowSetupWizardAsync() in OnLaunched
- Tray menu: 'setup' action now opens OnboardingWindow instead of SetupWizardWindow
- OnboardingCompleted event mirrors existing SetupCompleted reconnection logic
- Old ShowSetupWizardAsync() preserved for backward compatibility
- Full build passes clean

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

* Remove SetupWizardWindow, redirect all call sites to OnboardingWindow

- Remove ShowSetupWizardAsync() and _setupWizard field
- Redirect deep link OpenSetup handler to ShowOnboardingAsync()
- SetupWizardWindow.cs retained but no longer wired from App.xaml.cs
- All build.ps1 targets pass clean

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

* Sprint 1: Enhanced pages + shared widgets (4 parallel tasks)

Welcome Page (op-dlw):
- Lobster icon, security warning card with ⚠️, trust model bullet points
- Two-card layout (orange warning + gray trust explanation)

Connection Page (op-24b):
- Local/Remote/Later radio choices with ●/○ indicators and emoji icons
- Conditional gateway URL + token fields for Local/Remote modes
- Local pre-fills ws://localhost:18789, Test Connection button
- Two-way binding to OnboardingState and SettingsManager

Ready Page (op-qrh):
- 🎉 celebration icon, mode-specific info card
- Feature action rows with icon + title + subtitle
- Launch at Login toggle
- Configure Later / Remote info cards

Shared Widgets (op-5xl):
- OnboardingCard: Rounded card with white background
- FeatureRow: Icon + title + subtitle row component
- StepIndicator: Dot-based navigation indicator
- GlowingIcon: 🦞 lobster icon (animation-ready)

All 4 tasks implemented in parallel. Full build passes clean.

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

* OnboardingApp nav + localization (27 keys × 5 locales)

OnboardingApp (op-fix):
- Integrated GlowingIcon header and StepIndicator widget
- Layout matches macOS: icon → page content → nav bar
- Phase 3 placeholder pages with clear labels

Localization (op-4jl):
- 27 onboarding keys added to all 5 locale .resw files
- en-us, fr-fr, nl-nl, zh-cn, zh-tw
- Covers: title, nav buttons, welcome, connection, ready pages

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

* Sprint 2+3: All pages + polish (6 parallel tasks)

Wizard Page (op-y0w):
- Native offline fallback: gateway URL, token, node mode toggle
- Test Connection button with status feedback
- TODO comments for future WebSocket RPC integration

Permissions Page (op-9mr):
- 5 Windows permissions: Notifications, Camera, Mic, Screen Capture, Location
- Status indicators (/) with Open Settings buttons
- Status message area for feedback

Chat Page (op-e38):
- 'Meet your Agent' MVP chat UI
- Agent welcome bubble (blue) + user message bubbles (gray)
- Text input + Send button, footer note about full WebView2 integration

Mica + Theming (op-dl8):
- Non-resizable window via OverlappedPresenter
- Mica backdrop confirmed, window size matches spec

Page Transitions (op-xh9):
- Spring slide transition on NavigationHost (dampingRatio: 0.86)
- Matches macOS interactiveSpring(response: 0.5, dampingFraction: 0.86)

Accessibility (op-61d):
- To be enhanced in Sprint 4 integration pass

All pages wired into OnboardingApp. Full build passes clean.

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

* WizardStepView renderer + integration validation

WizardStepView (op-2oj):
- Dynamic renderer for all 7 gateway RPC step types
- Note, Text (with Sensitive/password), Confirm, Select, MultiSelect, Progress, Action
- WizardStepProps record + WizardStepType enum
- Switch expression renders type-appropriate UI with OnSubmit callback

Integration (op-28l):
- Solution file already includes OpenClawTray.Infrastructure (done in Sprint 0)
- build.ps1 builds WinUI with ProjectReference chain — no changes needed
- All 774 tests pass (652 Shared + 122 Tray, 0 failures)

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

* Add onboarding unit tests (13 new tests, 135 total Tray tests)

OnboardingStateTests:
- GetPageOrder: Local includes Wizard, Remote excludes it, Later is minimal
- GetPageOrder: NoChat mode excludes Chat for all modes
- GetPageOrder: Always starts with Welcome, ends with Ready
- Defaults: Mode=Local, ShowChat=true
- Complete: fires Finished event, calls Settings.Save()

All 774+ tests pass (652 Shared + 135 Tray, 0 failures).

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

* Add WizardStepProps and WizardStepType unit tests

Tests WizardStepType enum (7 values) and WizardStepProps record defaults.
All 145 Tray tests pass (0 failures).

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

* Add inner-loop dev scripts for testing onboarding UX

- dev-loop.ps1: Build + kill + launch cycle with -Clean (first-run) and -Tail (logs)
- test-sandbox.wsb: Windows Sandbox config with mapped build output for clean-state testing
- setup-sandbox-network.ps1: Port proxy setup for sandbox-to-WSL gateway connectivity

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

* Fix NullRef on first render, duplicate lobster, Border(null!) crash

- OnboardingWindow: use ctx.UseState(state) in mount function for props persistence
- WelcomePage: remove duplicate lobster icon (OnboardingApp header has the persistent one)
- StepIndicator: Border(TextBlock('')) instead of Border(null!) to avoid runtime NullRef

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

* Fix nav bar positioning + visual test framework + bug fixes

Nav bar fix:
- Fixed NavigationHost height to 520px so nav bar stays at consistent position
- All pages render within the same content area, nav bar never jumps
- Replaced Spring transition with 200ms Slide (prevents overlap on fast navigation)
- Compacted WelcomePage: merged security+trust cards, reduced font sizes
- Reduced GlowingIcon from 64px to 48px, tightened margins

Bug fixes:
- Fixed NullRef on first render (ctx.UseState for mount props persistence)
- Fixed duplicate lobster icon (removed from WelcomePage, kept in OnboardingApp header)
- Fixed Border(null!) crash in StepIndicator

Visual test framework:
- visual-test.ps1: P/Invoke window finding + UIAutomation button clicking
- Screenshot capture via PrintWindow/CopyFromScreen (note: GDI capture fails on Dev Box/Cloud PC)
- Baseline + after screenshots in visual-test-output/

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

* SlideInOnly transition + RenderTargetBitmap visual capture

SlideInOnlyTransition (NavigationTransition.cs + TransitionEngine.cs):
- New transition type: instantly hides old page (opacity=0), slides+fades new in
- Direction auto-reverses on back nav (Push=right, Pop=left)
- 200ms duration with cubic-bezier easing
- Zero flicker — old page is invisible before new one starts animating

RenderTargetBitmap visual capture (OnboardingWindow.cs):
- In-app capture via WinUI RenderTargetBitmap API
- Works on Dev Box/Cloud PC (no physical display needed)
- Triggered by OPENCLAW_VISUAL_TEST=1 env var
- Auto-captures on initial load and every page navigation (PageChanged event)
- Saves PNGs to OPENCLAW_VISUAL_TEST_DIR
- All 6 pages validated via LLM visual analysis

OnboardingState.cs:
- Added PageChanged event for capture integration

All 145 tests pass. Full build clean.

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

* Fix Permissions page button alignment: use Grid layout for right-aligned buttons

Changed PermissionRow from HStack to Grid with ['1*', 'Auto'] columns so
'Open Settings' buttons are consistently right-aligned and stacked vertically,
matching the pattern used in ConnectionPage.cs.

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

* Fix Permissions page: left-align status emojis in own column

Move status emojis (, , ⚠️) from inline with permission name into
a dedicated Grid column 0 with Auto width. Changes the row Grid from
2 columns [1*, Auto] to 3 columns [Auto, 1*, Auto]:
- Column 0: Status emoji, fixed width, left-aligned
- Column 1: Permission icon + name + description, fills remaining
- Column 2: Open Settings button, right-aligned

This ensures all status emojis form a clean vertical line.

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

* wip: latest onboarding fixes pre-upstream-merge

Checkpoint of in-progress work before merging origin/master to pick up
GatewayTopologyClassifier, SshTunnelCommandLine, SshTunnelService, and
updated SettingsWindow connection logic.

Includes:
- Permissions page alignment fixes
- ConnectionPage gateway auth + pairing flow
- New onboarding services (GatewayHealthCheck, InputValidator,
  LocalGatewayApprover, PermissionChecker, SetupCodeDecoder,
  WizardStepParser)
- Tests for those services
- Localization keys across 5 locales
- Inner-loop dev scripts and e2e helpers
- Onboarding + auth-fix proposal docs

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

* feat(onboarding): redesign Connection page to match new UX mockup

Implements the redesigned Connection page from connection-page-mockup.html:

- Five gateway modes (was three): Local / WSL / Remote / SSH Tunnel /
  Configure Later. WSL and SSH are added to ConnectionMode and reuse
  the Local page-order in OnboardingState.GetPageOrder().
- Setup Code row gains explicit Paste and QR-import buttons in addition
  to the existing focus-paste behavior. QR decoding is extracted from
  SetupWizardWindow into a reusable Helpers/QrSetupCodeReader so it can
  be invoked from Reactor pages without depending on the wizard window.
- Animated SSH panel renders inline when SSH mode is selected: 2x2 grid
  of SSH User / Host / Remote Port / Local Port plus a live preview line
  generated via SshTunnelCommandLine.BuildArguments(...). Settings are
  written through to SettingsManager.SshTunnel*. App gains a
  EnsureSshTunnelStarted() shim so TestConnection can spin up the
  managed tunnel before health-checking ws://127.0.0.1:<localPort>.
- Topology detection line renders the GatewayTopologyClassifier output
  (DisplayName/Transport/Detail) live as the user changes modes / SSH
  fields, matching the mockup's '● Detected: ...' line.
- Page content is wrapped in a ScrollView and the onboarding window is
  resized to 720x900 to fit the additional rows in the SSH layout.
- App exposes GetOnboardingWindowHandle() so the QR FileOpenPicker can
  initialize against the onboarding HWND.
- Two new optional environment variables aid visual testing without
  requiring UI automation:
    * OPENCLAW_ONBOARDING_START_ROUTE = <OnboardingRoute name>
    * OPENCLAW_ONBOARDING_START_MODE  = <ConnectionMode name>

Adds new locale keys for the SSH/WSL/QR/Topology surface in all five
locales (en-us authoritative; fr-fr, nl-nl, zh-cn, zh-tw machine-
translated and flagged for human review in the PR description).

Adds tests/OpenClaw.Tray.Tests/ConnectionPageTopologyTests.cs covering:
- 5-mode page-order parity (Wsl/Ssh behave like Local).
- GatewayTopologyClassifier outputs for the canonical mode→URL mapping.
- SshTunnelCommandLine preview includes both forwards (gateway +
  browser-proxy +2) and validates user/host.

Validation (per AGENTS.md):
- ./build.ps1: all projects succeed.
- dotnet test Shared:  967 passed / 20 skipped / 0 failed.
- dotnet test Tray:    350 passed / 0 failed (8 new).
- Visual capture in OPENCLAW_VISUAL_TEST mode for both Local and SSH
  modes; matches mockup layout.

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

* security: remove hardcoded WSL gateway dev token from e2e test

The fallback token was a dev-gateway secret that got flagged by GitHub secret scanning. Token now must come from WSL openclaw.json (preferred) or OPENCLAW_GATEWAY_TOKEN env var; the script fails fast if neither is available.

Note: the leaked token should be rotated by regenerating the dev gateway config in WSL.

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

* chore(infra): prune unused Reactor modules (Charting/Data/Yoga/FlexPanel/DataGrid/PropertyGrid)

Per PR feedback: the tray only uses Core/Hosting/Navigation/Elements/Hooks/
Animation/Markdown/Accessibility/Input from the Reactor snap. Removed:
- Charting/ (D3 charts not used by onboarding)
- Data/ (datasource/grid binding not used)
- Yoga/ (FlexPanel not used; tray uses StackElement-based HStack/VStack)
- Controls/DataGrid (cascading: depends on Data+Charting)
- Controls/PropertyGrid (cascading: depends on Data)
- Pruned Yoga/FlexPanel hooks from Core/Element.cs, ElementPool.cs,
  Reconciler.Mount.cs, Reconciler.Update.cs, Elements/Dsl.cs, ElementExtensions.cs
- Pruned Charting hooks from Core/AccessibilityScanner.cs and Hosting/ReactorHost.cs
- Removed UseDataSource from Core/Component.cs
- Removed FieldDescriptor overload from Controls/Validation/FormField.cs
- Removed ResizeGripRegistration call sites (lived in DataGrid)

Build clean. Tray tests 350/350 pass. Shared tests 967/967 pass.

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

* refactor(onboarding): replace Reactor snap with FunctionalUI helper

Replace the vendored Reactor-derived infrastructure project with a tiny OpenClaw-owned FunctionalUI helper layer used by onboarding.

Remove unused charting, data, markdown, devtools, validation, localization, input, animation, and broad control infrastructure from the PR.

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

* chore: remove local workflow files from onboarding PR

Remove Beads and Gastown hook files so the tray onboarding PR only contains product UI changes and required app support.

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

* chore: remove extraneous artifacts from onboarding PR

Remove local visual outputs, sandbox/provisioning scripts, e2e scratch automation, and upstream planning docs from the tray onboarding PR.

Keep the remaining changes focused on the product onboarding flow and supporting app code.

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

* Fix tray onboarding runtime issues

Remove inconsistent gray onboarding panels, stabilize connection mode selection, fix FunctionalUI reparenting during conditional renders, and add runtime hooks needed for tray window capture and WebChat error rendering.

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

* Address onboarding pairing feedback

Remove the local gateway auto-approval shortcut and use the existing pairing command copy/notification flow instead. Also scope bootstrap operator handshakes to the gateway handoff profile, skip Chat for Configure Later, and dispose onboarding state safely.

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

* Constrain bootstrap auth to onboarding setup codes

Keep the default gateway client auth payload and chat URL construction aligned with the existing tray app, while allowing onboarding setup-code handoff to opt into bootstrap auth scopes explicitly.

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

* Tighten gateway security follow-ups

Preserve MCP-only onboarding completion routing, remove the unused public connect auth token getter, and add regression coverage for default operator scopes and paired bootstrap handoff auth.

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

---------

Co-authored-by: Mike Harsh <mharsh@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-01 09:12:35 -07:00
Vincent Koc
29510a16eb
test: authorize MCP readiness probe
Some checks are pending
Build and Test / release (push) Blocked by required conditions
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
2026-04-30 02:46:38 -07:00
Vincent Koc
424f69083b
fix(security): require MCP auth before method dispatch 2026-04-30 02:36:14 -07:00
Scott Hanselman
5ef3707509 chore: clean root artifacts and rename solution
Remove tracked root diff and merge-analysis artifacts that were left from prior PR review work.

Rename the solution file from the historical moltbot-windows-hub.slnx to openclaw-windows-node.slnx and update docs/tests that use it for developer guidance or repo-root discovery.

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 build ./openclaw-windows-node.slnx --no-restore.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 01:00:20 -07:00
Chris Anderson
9fa43f3477
feat: add native WinUI A2UI renderer and MCP hardening (#239)
Adds the native WinUI A2UI rendering pipeline, MCP/local security hardening, navigation/media safeguards, and integration/UI coverage for tray-hosted A2UI surfaces.\n\nThanks to @codemonkeychris for the substantial implementation and follow-through on review feedback.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-29 22:53:50 -07:00
github-actions[bot]
c7630fa008
[Repo Assist] feat: wire WebView2 bidirectional nativeΓåöSPA bridge in WebChatWindow
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
Adds the WebView2 native-to-SPA bridge and hardens it with origin validation, dispatcher marshaling for native posts, closed-window guards, sanitized bridge logging, and validated payload JSON.\n\nValidated locally with build.ps1, Shared tests, and Tray tests; GitHub CI is green.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 20:25:28 -07:00
github-actions[bot]
e35da4b6a4
[Repo Assist] test: add CommandCenterDiagnostics and ScreenCapability coverage
Resolved conflicts against current master and validated locally.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:50:33 -07:00
dependabot[bot]
e217438026
chore(deps): bump actions/setup-dotnet from 4 to 5
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:26:53 -07:00
dependabot[bot]
aa093339f7
chore(deps): bump github/gh-aw-actions from 0.68.3 to 0.71.1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:26:49 -07:00
dependabot[bot]
6cfb8af383
chore(deps): bump actions/cache from 4 to 5
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:26:44 -07:00
dependabot[bot]
30d02486ac
chore(deps): bump softprops/action-gh-release from 2 to 3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:26:40 -07:00
dependabot[bot]
209bf6fccc
chore(deps): bump actions/checkout from 4 to 6
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:26:36 -07:00
Scott Hanselman
e63228e87e fix: polish tray submenu flyouts
Add monitor-aware cascading submenu windows for tray flyouts, apply rounded HWND clipping so corners do not reveal the backing window, and reduce hover repaint flicker by reusing flyout windows with no-activate tool-window styling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 18:13:07 -07:00
Scott Hanselman
f7800d87fe Merge PR #234 local MCP server mode
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
Copilot Setup Steps / copilot-setup-steps (push) Waiting to run
Adds the Windows tray local MCP HTTP server mode with loopback-only transport hardening, localized Settings UI, MCP-only startup support, and test coverage for the JSON-RPC bridge, HTTP security gates, cancellation, shutdown drain, and capability argument clamps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 11:50:33 -07:00
Chris Anderson
ced450f53c fix: localize MCP settings strings and lock capability list
Two follow-ups from code review:

1. Hardcoded i18n strings in SettingsWindow are now resource-driven.
   New x:Uid bindings cover the MCP toggle header, description,
   Endpoint/Status labels, plus a new "Developer Mode" section header
   above the toggle so the use case is visually scoped. Status text
   ("Disabled", "Listening", "Stopped", "Will start/stop on Save",
   "Failed to start: ") routed through LocalizationHelper. Translations
   added to en-us, fr-fr, nl-nl, zh-cn, and zh-tw. The diagnostic detail
   appended after "Failed to start:" intentionally stays in English —
   it embeds a literal `netsh http add urlacl` command that does not
   localize meaningfully.

2. NodeService._capabilities is now guarded by _capabilitiesLock on
   every read and write. The MCP bridge was previously snapshotting
   _capabilities.ToArray() on threadpool threads while the UI thread
   could be in the middle of RegisterCapabilities (Clear + adds). Low
   probability but real — a tools/list mid-rebuild could observe an
   empty or partial list. RegisterCapabilities now holds the lock for
   the full sync rebuild; DisconnectAsync's Clear and the bridge
   snapshot lambda also take it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:42:07 -07:00
Chris Anderson
353a4b9a53 fix: address GPT 5.5 review feedback for local MCP server
Per code review (GPT 5.5), tightens stability and operability of the
local MCP transport without changing the loopback-only trust model.

CR-003 — bound request and tool execution
  * McpHttpServer: per-request linked CTS with 90s deadline; CT propagated
    through ReadBodyAsync (slow-body defense) and bridge dispatch.
  * McpToolBridge.HandleRequestAsync(body, ct) overload uses Task.WaitAsync
    so a wedged tool surfaces as a "request timed out" tool error instead
    of pinning a handler slot.
  * SystemCapability.HandleRunAsync clamps timeoutMs <= 0 to the default
    and caps at 10 minutes — closes the "wait forever" hole that
    LocalCommandRunner.TimeoutMs <= 0 previously enabled.

CR-005 — drain in-flight handlers before disposal
  * Track active handler tasks; StopAsync(drainTimeout) cancels CT, stops
    the listener, awaits in-flight handlers (5s) before Dispose tears the
    semaphore down. Removes the Task.Run(..., ct) cancellation race that
    could leak a slot, and defensively swallows ObjectDisposedException
    on semaphore release during shutdown.

CR-007 — clamp arguments at the capability boundary
  * Screen / camera / canvas capabilities now clamp dimensions, quality,
    monitor index, durations, fps, and window position to safe ranges
    before any allocation. camera.clip floor-clamps duration so 0/-N can
    no longer slip through the original Math.Min cap.

CR-008 — surface MCP startup status in Settings
  * Categorize HttpListenerException by NativeErrorCode (5 = URL ACL
    access denied with the exact netsh remediation; 32/183 = port in use).
  * Settings status replaces the misleading "save and restart" wording
    with "Will start/stop on Save", reflecting the OnSettingsSaved flow
    that reinitializes services immediately.

Tests: 22 new test cases (timeout tool error, dispose-during-handler
hygiene, slow-body recovery, clamp behavior). Full Shared.Tests suite
remains green at 933 passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 10:35:07 -07:00
Chris Anderson
86dad64f11 fix: harden local MCP server (CSRF, body cap, concurrency, tests)
Addresses review of the initial MCP HTTP server cut. Loopback bind alone
does not protect against browser-driven attacks — any page in the user's
browser is also on loopback. Adds a three-layer security gate, a body
size cap, a handler concurrency limit, and full HTTP-transport coverage.

Security
- McpHttpServer rejects requests with an Origin header (browsers always
  set it; real MCP clients never do). Validates Host against loopback
  names (DNS-rebinding pivot defense). Requires application/json on
  POST so a cross-origin browser fetch must trigger a CORS preflight,
  which we never satisfy.
- 4 MiB body cap with bounded streaming read (413 on overrun).
- 8-handler concurrency cap so a misbehaving local client cannot pin
  every threadpool thread on long-running screen/camera calls.
- Settings migration: legacy McpOnlyMode=false no longer silently
  inherits EnableNodeMode (would have flipped MCP on without consent).

Bridge
- _capabilities snapshotted to array per call (was racing concurrent
  enumeration vs UI-thread mutation).
- Non-integer / out-of-range / string ids round-trip via GetRawText
  instead of GetInt64 (used to strip the id from error responses on
  fractional or big-int ids, breaking client correlation).
- tools/call validates 'arguments' is an object if present and rejects
  empty 'name'.
- Generic 'internal error' on the wire for unhandled exceptions; full
  exception with stack goes to the log via Error(string, Exception).
- Empty resources/list and prompts/list for Cursor compat (was
  MethodNotFound).
- Non-object root → InvalidRequest.

Lifecycle
- Start() failure now disposes the half-constructed listener/CTS
  instead of leaking the port reservation.
- _disposed guarded with Interlocked.Exchange (idempotent across
  threads).
- App.xaml.cs warns when both modes are enabled but gateway
  prerequisites are missing — silent fall-back to MCP-only was
  confusing.
- NodeService.McpStartupError surfaces the actual failure to Settings
  UI; status text shows 'Failed to start: <reason>' instead of the
  misleading 'Stopped — save and restart to start'.

Refactor
- McpHttpServer moved from OpenClaw.Tray.WinUI/Services to
  OpenClaw.Shared/Mcp (no WinUI deps; lets it be unit-tested).

Tests
- 10 new McpToolBridgeTests: non-object root, missing/non-string
  params, non-object arguments, fractional/big-int/string ids,
  empty resources/prompts, generic-message guarantee on internal
  errors.
- New McpHttpServerTests (13): GET probe, valid POST, Origin reject,
  rebind-Host reject, localhost-Host accept, text/plain reject,
  json+charset accept, PUT reject, oversized body reject, notification
  204, idempotent dispose, ctor null guards.

Docs
- MCP_MODE.md: rewritten Security Model section with the three-layer
  model and curl-based 'verify the gate' examples; tool list updated
  to reflect master (screen.snapshot, camera.clip, location.get).

All 715 tests pass (32 MCP, 20 integration, 663 other).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 09:33:09 -07:00
Chris Anderson
a3d884f4c4 feat: local MCP HTTP server mode, independent of node mode
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 09:33:09 -07:00
Scott Hanselman
c64484e392 docs: document release flow
Document the tag-driven release process, versioning expectations, and retagging steps for OpenClaw Windows Hub releases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 08:54:11 -07:00
Scott Hanselman
124f488d3f fix: localize support diagnostics labels
Move the new tray Support & Debug and Command Center labels into localized resources across all supported tray locales. Update tray markup coverage so the compact diagnostics menu keeps using resource-backed labels instead of English literals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 07:36:14 -07:00
Scott Hanselman
811b848514 Merge mission-control parity and tray UX polish
Bring in the Windows tray parity work: Command Center support/debug entrypoints, diagnostics and summary copy surfaces, compact tray flyouts, Activity Stream history expansion, browser proxy guidance, manual update checks, SSH tunnel restart access, and refreshed Mission Control parity documentation.

Remaining parity blockers are intentionally documented: browser.proxy live smoke still needs matching gateway/browser-control auth or remote host setup, and Voice/TTS remains blocked pending a shared Mac/gateway contract and safer PR split.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 07:16:38 -07:00
Scott Hanselman
2bcfaf17d5 feat: further compact tray flyouts
Group recent activity previews and support file shortcuts into flyouts so the main tray menu stays compact while preserving all existing actions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 07:16:19 -07:00
Scott Hanselman
a38674e6aa feat: compact support diagnostics tray menu
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 07:10:23 -07:00
Scott Hanselman
65542764f2 docs: sync mission control parity status
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 07:01:37 -07:00
Scott Hanselman
64a5221e99 feat: expand activity stream history
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:56:30 -07:00
Scott Hanselman
6b880ccf96 feat: expose tray diagnostics copy actions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:49:09 -07:00
Scott Hanselman
dd51149a5e docs: record voice mode parity blockers
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:45:57 -07:00
Scott Hanselman
16d3003356 feat: add tray ssh restart action
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:38:48 -07:00
Scott Hanselman
62d7e0c28b feat: add debug bundle entrypoint
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:32:21 -07:00
Scott Hanselman
4184e12751 feat: add tray support debug actions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:24:13 -07:00
Scott Hanselman
ec4ce4aafc feat: add summary copy entrypoints
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:17:46 -07:00
Scott Hanselman
582cec5557 feat: add diagnostics copy entrypoints
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:13:14 -07:00
Scott Hanselman
51c14f38d1 feat: add port diagnostics entrypoint
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 06:08:12 -07:00
Scott Hanselman
65339ab658 feat: add manual update check entrypoint
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 05:57:54 -07:00
Scott Hanselman
8bba19ca9d feat: add browser setup guidance entrypoint
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 05:44:45 -07:00
Scott Hanselman
cd67ae8485 fix: preserve packaged deeplink registration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 05:21:39 -07:00
Scott Hanselman
0ca2014244 fix: redact support context paths
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 05:13:58 -07:00
Scott Hanselman
18b43a50e8 feat: add support debug entrypoints
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 05:04:09 -07:00
Scott Hanselman
7fa9aef4d1 fix: report ssh restart failures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 04:54:21 -07:00
Scott Hanselman
9a4fe87642 docs: update mission control parity status
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-27 04:52:21 -07:00