Conversation
* 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>
…#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>
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>
…icy (openclaw#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>
…provals.set (openclaw#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>
…ge coverage gaps (openclaw#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>
…nclaw#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>
…penclaw#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>
…w#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>
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 openclaw#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>
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 openclaw#240. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Allow WindowsNodeClient to bootstrap from an already-paired device token when the original gateway/bootstrap token is no longer present in settings. Add a side-effect-free DeviceIdentity helper for reading a persisted device token without generating a new identity file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Treat a stored node device token as setup-complete state so already-paired nodes do not re-open onboarding after restart. Skip operator gateway initialization when no operator token exists, preventing the empty-token crash path on clean or local-only profiles. Make setup identity lookup respect OPENCLAW_TRAY_DATA_DIR and cover startup setup decisions with tray tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the first V2 exec-approval input-validation slice for system.run requests.\n\nThis introduces a structural validator and validated request DTO without wiring it into production execution yet, so existing system.run behavior stays unchanged while the next approval-policy phases get a tested foundation.\n\nValidated locally on the PR branch and on the current-master merge result with .\\build.ps1, Shared tests, and Tray tests.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use WinUI semantic theme brushes for onboarding surfaces instead of hardcoded light card colors. Add FunctionalUI support for resource-backed backgrounds and cover onboarding with a regression scan so dark mode does not regress. Validated with .\build.ps1, Shared tests, Tray tests, and a visual dark-mode onboarding pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ine toggles Consolidate 8 separate windows into a single Hub app: - New HubWindow with NavigationView (Chat, Home, Activity, Settings pages) - Chat page embeds gateway Control UI via WebView2 (default landing page) - Home page with live status cards, quick actions, and activity feed - Settings page with Expander sections, Test Connection, SSH tunnel fields - Activity page with category filters and live ActivityStreamService binding - Slim tray menu: status + 3 inline toggles + Hub/QuickSend + Settings/Exit - Acrylic backdrop on tray flyout, auto-collapsing nav, page transitions - Deep links (openclaw://) redirected to Hub pages - Deleted 5 old windows: StatusDetail, ActivityStream, NotificationHistory, WebChat, Settings - WebView2 event handler cleanup on page Unloaded (code review fix) - Deferred page init to avoid null Settings during Frame.Navigate 25 files changed, 1350 insertions(+), 2033 deletions(-) — net code reduction Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tunnel support - Settings save validates gateway URL and SSH tunnel fields before saving - Test Connection supports SSH tunnel mode (starts temp tunnel for test) - SSH toggle auto-updates gateway URL field (shows loopback in tunnel mode) - Chat page injects CSS to hide web Control UI sidebar (no dual navigation) - Tray toggle switches hide On/Off labels to prevent clipping Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nd live gateway data New pages: Sessions, Channels, Usage, Nodes, Cron, Skills, Config, About - Sessions: live session list with reset/delete/compact actions - Channels: channel health cards with start/stop controls - Usage: cost breakdown, provider stats, daily costs - Nodes: node inventory with capabilities and device ID copy - Cron: scheduled jobs with run/remove actions (gateway wired) - Skills: installed skills status (gateway wired) - Config: TreeView + detail panel with editable values via config.set protocol - About: version info, debug tools, documentation links Infrastructure: - Dual WebSocket connection: operator client (UI data) + node client (commands) - 14 new gateway methods: cron.*, skills.*, config.* with JsonElement.Clone() - Data caching in HubWindow for instant page navigation - Session startedAt parsing fix (handles number + string timestamps) - Hub window synced after settings reconnect - Tray test updated for Auto scrollbar Build: 0 errors | Tests: 774 passing (652 shared + 122 tray) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…redesign, timer removal Features: - Agent Events page with stream filters and 400-event ring buffer - Gateway discovery via mDNS (Zeroconf) with scan UI in General page - Node/Device pairing UI with approve/reject in Nodes page - Models list in Sessions page via models.list gateway method - Instances page rewired to presence data from handshake snapshot - Context cards in tray menu (session summary + token usage bars) - Pairing pending count in tray menu Menu & UX: - Merged status + toggle into rich header card with status dot - Permission toggles section (browser, camera, exec, canvas, screen) - Renamed hub to Windows Companion with smart disconnect navigation - Custom title bar with live connection status + gateway version - Single-click tray -> chat, double-click -> hub - Chat window pre-warmed on startup, hides instead of closing Architecture: - Removed all background timers (10s poll + 30s health check) - On-demand data loading only (pages fetch on navigation) - Fixed ParseSessions to merge instead of clear-then-rebuild (no flicker) - Fixed HandleAgentEvent sessionKey parsing (was reading from root, not payload) - Symmetric subscribe/unsubscribe for all new gateway events - Caches cleared on disconnect, seeded into HubWindow on open Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace flat Agent section with hierarchical Agents > {agentId} > {sub-pages} structure
- Move Conversations shortcut to top level, pointing to SessionsPage
- Remove AgentSelectorNav ComboBox, replaced with dynamic nav tree (RebuildAgentNavItems)
- Add FindAndSelectNavItem for recursive nested nav item selection
- Add agent: tag parsing (ResolveAgentPageType, ParseAgentIdFromTag)
- Update NavigateTo with legacy flat tag mapping to new agent: prefix format
- Strip Zone B (Agent Roster) and Zone C (Capability Toggles) from HomePage
- Remove Node Mode toggle from SettingsPage (lives in CapabilitiesPage)
- Update command palette to use agent-scoped tags
- NavigateToDefault now goes to Home instead of Conversations
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… APIs Navigation restructure: - 16 flat pages → domain-grouped hierarchical nav (Gateway, This Computer) - Each agent gets expandable nav item with Sessions, Events, Skills, Workspace - Dynamic agent nav built from agents.list gateway response - Nodes nested under Instances (superset relationship) - Cron moved to gateway section (gateway-wide, not per-agent) - Connection page extracted from Settings into Gateway section - Settings simplified to local-only (startup, notifications) New pages: - ConnectionPage — gateway URL, token, SSH tunnel, discovery, status - CapabilitiesPage — device toggles + node status indicator - WorkspacePage — TabView per-file viewer via agents.files.list/get - BindingsPage — routing rules viewer (channel→agent) - ConversationsPage — cross-agent session browser (legacy) Command palette (Ctrl+K / Ctrl+F): - Inline overlay with light dismiss (click outside, Escape, Enter) - 20+ navigation + 5 toggle + dynamic session commands - Fuzzy substring filtering Home page (The Hearth): - Molty status indicator with colored ring - Natural language status text - Quick action buttons Agent-scoped data: - Sessions, Skills pass agentId to gateway calls - Agent Events filtered by sessionKey prefix - Workspace scoped to current agent in hierarchy Real gateway APIs: - agents.list → dynamic nav + agent roster - agents.files.list/get → workspace file viewer - Cached agents list for hub seeding on open Architecture: - Canvas window styled with Mica + custom title bar - Open Canvas menu item uses NodeService.ShowCanvasWindow() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add rich ToolTip to each session label showing model, provider, channel, thinking level, token breakdown, context window, status, and age - Add Connected Devices section between context summary and Permissions with online indicator dots, platform badges, and rich tooltips - Show connected client count from presence data in status header subtitle Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace plain text session/device rows with structured Grid cards featuring: - Status dot (green/amber/gray) + name + model/platform badge + chevron - Token usage with percentage and color-coded progress bar - Channel badges and capability icons for devices - Section headers with right-aligned summary stats Add AddFlyoutCustomItem() to TrayMenuWindow for custom UIElement flyout items with hover-to-show and click-to-navigate behavior. Build detailed side flyout panels with headers, token breakdowns, capability listings, and session metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Chat panel: - Tray-anchored borderless popup (bottom-right, DPI-aware) - WS_EX_TOOLWINDOW + no caption/frame (hidden from taskbar) - Auto-hide on deactivate, instant show (no animation — WebView2 incompatible) - Single-click toggle, double-click opens Hub (400ms detection) - Chat window recreated on settings change (stale URL fix) Tray menu: - Rich 2-line session cards: status dot, model badge, token progress bar - Rich device cards: capability emoji strip, platform badge - Flyout detail panels: non-interactive TextBlocks (not menu items) - Session flyout: model/provider, channel, ASCII token bar, thinking/verbose - Device flyout: capabilities merged with commands (cap as header, cmds indented) - Dynamic capability toggles under local device (from node.Capabilities) - Flyout dismisses on any menu item hover (including separators/headers/toggles) - Section headers with aggregates (sessions/tokens, online/caps) - AddFlyoutCustomItem + AddToggleItem indent support Schema config editor: - SchemaConfigEditor UserControl renders from JSON Schema - Supports string/number/boolean/enum/array/nested objects - Sensitive field detection (PasswordBox) - Fallback RenderConfigDirectly when schema unavailable - Config detail panel uses schema for selected tree node - Pending changes preserved on save failure Command palette: - Rebuilt as inline overlay Grid (light dismiss: Escape + click-outside) - Ctrl+F added as alternate shortcut - TextBox replaces AutoSuggestBox (proper Escape handling) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Connection Management: - Redesigned ConnectionPage with 6-section card layout: status card with live gateway info, gateway discovery picker with mDNS scan, setup code paste (from openclaw qr), manual connection expander, device identity card with pairing status and copyable approval command, connection log - Auto-discovery when disconnected or unconfigured - Setup code applies both bootstrapToken and Token for immediate connect - PreferredGatewayId persisted in settings Tray Menu Polish: - Compact 3-column ToggleButton grid for capability toggles (all 7 shown) - Split header subtitle into 2 lines (connection details + node status) - Auth failure warning shown inline - Reconnect and Connection quick actions - Dropped 'Open' prefix from action items, added bottom padding Hub Window: - Removed XAML KeyboardAccelerators (caused tooltip flicker on hover) - Replaced with PreviewKeyDown handler for Ctrl+K/F - Added ReconnectAction, LastGatewaySelf, node state properties Connection Lifecycle Fixes (from 3-model rubber-duck review): - Capability toggles now use ReconnectNodeServiceOnly() instead of full teardown — no longer kills gateway client or chat window - Reconnect action uses lightweight ReconnectGateway() (preserves chat) - SyncHubNodeState() pushes live pairing/identity to hub on every node status and pairing change - Gateway matching uses host:port comparison (not full URL with scheme) - Discovery service disposed on page Unloaded - Connection log refreshes on every status change - SanitizeUrl guards against port -1 - Null-conditional restored on _hub?.RaiseSettingsSaved() - Synthesized current gateway entry doesn't mutate cached list Other: - Instant single-click chat toggle (removed double-click debounce) - Catch-all ShowHub(action) for menu nav tags - SSH tunnel section flattened (removed redundant nested expander) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Session flyout: - Replaced ASCII token bar (█░) with WinUI ProgressBar (green/orange/red) - Built flyout as native UIElement (StackPanel) instead of text items - Added AddFlyoutCustomItem(UIElement, UIElement, action) overload Title bar search: - Replaced hidden command palette overlay with AutoSuggestBox in title bar - Standard Windows pattern, always visible, Ctrl+K/F focuses it - Lobster icon 14px → 20px, title shortened to 'OpenClaw' - Removed overlay XAML, smoke layer, and palette methods MCP server toggle: - Added Local MCP Server card on Capabilities page - Toggle, endpoint URL display, Copy Token/URL buttons - Shows token readiness status Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replaced custom UIElement session flyout panel with simple TrayMenuFlyoutItem list matching the device flyout pattern. ProgressBar stays in the main menu session card only. Removed unused AddFlyoutCustomItem(UIElement, UIElement) overload and ShowCascadingFlyoutElement helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Navigation:
- Sessions, Agent Events, Skills promoted to top-level with agent filter
- Agents folded to one level (direct nav → Workspace)
- Instances merged into Nodes with Connected Clients section
- Title restored to 'OpenClaw Windows Companion'
- Title bar: 48px height, responsive search (Ctrl+E), lobster 20px
Config page:
- Schema-driven tree (objects only, no leaf nodes)
- Editor + Raw JSON tabs
- config.patch sends { raw, baseHash } (hash from config.get response)
- Subtitle shows actual config file path from gateway
- All expanders open by default
App MCP capability (10 tools):
- app.navigate/status/sessions/agents/nodes/config.get
- app.settings.get/set with security allowlist (no secrets)
- app.menu/search for tray and command palette testing
- All handlers return structured data (not stringified JSON)
- Sessions filter by session key prefix (not channel)
Bug fixes:
- AgentEventsPage: init NRE guard, filter applies to display
- CapabilitiesPage: MCP toggle suppress during init
- SessionsPage: removed unused agent filter
- Config save: proper baseHash from gateway hash field
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes from Opus 4.7, Sonnet 4.5, GPT-5.4, GPT-5.2, Opus 4.6 reviews: - Guard IndexOutOfRangeException on empty session Status - Fix TCS hang when DispatcherQueue unavailable in app.navigate - Static s_emptyObject replacing leaked JsonDocument in config tree - Always prune stale sessions (removed incomingKeys.Count > 0 guard) - try/catch/finally on 6 async void handlers (Channels, Sessions, Config) - Seed ALL cached data before NavigateToDefault in ShowHub - Move CurrentStatus/_cachedCommands inside DispatcherQueue in UpdateStatus - Raw JSON tab uses 'parsed' not wrapper object - Null-safe Subtitle in search handler - Invalidate command cache on agent switch - Dispose SemaphoreSlim in GatewayDiscoveryService Regression tests (9 new): - AppCapabilityTests: category, commands, CanHandle, handlers, errors - SessionInfo empty Status guard - ParseSessions empty array clears sessions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Header:
- Split into brand header (🦞 OpenClaw) + Gateway section
- Gateway section: status dot, version/host:port, node status, labeled
ToggleButton ('Connected'/'Disconnected') with tooltip
- Gateway info clickable → opens Connection page
- Menu dismisses after connect/disconnect toggle (avoids stale header)
Dismiss:
- Unified 150ms delayed foreground check for all deactivation cases
- Checks this window, flyout child, and owner parent before dismissing
- Fixes: click-away dismisses everything, hover between items doesn't
- Set _isShown=true in ShowAtCursor (was missing, broke dismiss guard)
Sessions:
- Removed connection status gate — show cached sessions always
- Zero gateway requests on menu open (health check was clearing sessions
via ParseSessions in the response)
- Session cards click → 'sessions' top-level route
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…itching Discovery: - Localhost probe enumerates listening TCP ports via GetActiveTcpListeners - Probes for gateway HTML signature (<title>OpenClaw Control</title>) - Excludes MCP port (8765) to avoid false positives - Runs in parallel with mDNS, results merged Connection page: - Auth error InfoBar with contextual guidance (token/pairing/password/signature) - HubWindow.LastAuthError forwarded from OnAuthenticationFailed - Cleared on successful connect and new connection attempts - Token prompt always shows when switching gateways (pre-fills current token) - Cancel button on token prompt - Discovery list refreshes after connecting to show ✓ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix gateway discovery host resolution, harden branch-introduced security paths, complete localization coverage, remove newly introduced dead code, refresh documentation, wire functional UX flows, and stabilize the Config page rendering path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Initialize the local node service when MCP mode is enabled even if gateway node mode is disabled, so MCP-only tray launches start the HTTP server used by integration tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reviews performed
Security review
Performed a STRIDE-oriented security review of the UX branch against
master, covering:Changes from that review include:
127.0.0.1) to avoid WindowslocalhostURLACL startup failures.Localization review
Reviewed branch changes against the existing localization standards from
master:x:Uid.LocalizationHelper.GetString..reswkey sets must match across all locale directories.Changes from that review include:
x:Uidcoverage for branch-added Companion UI, onboarding, tray, and window strings.en-usfr-frnl-nlzh-cnzh-twmaster.Dead-code and churn review
Reviewed branch-introduced code for unused or stale surfaces after UX churn.
Changes from that review include:
Functional UX smoke pass
Performed a functional UX smoke pass over the Companion UI/navigation/data wiring.
Areas checked:
Changes from that review include:
CronStatusUpdatedthrough gateway client → app → hub → Cron page.openclaw://historyto Activity filtered to notification history.Documentation review
Checked existing Markdown files for stale UX references and updated docs accordingly.
Updated areas include:
Validation
git diff --check.\build.ps1dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restoreResults: