refactor(openclaw): delegate gateway to OS service manager with Windows compatibility#13165
Draft
refactor(openclaw): delegate gateway to OS service manager with Windows compatibility#13165
Conversation
…e dead fields
- Extract repeated `{ success: boolean; message: string }` into
`OperationResult = { success: true } | { success: false; message: string }`
- Success path no longer carries unused message strings
- Unify restartGateway return type (was `message?: string`, now consistent)
- Remove never-populated `uptime` and `version` from HealthInfo
- Update preload and renderer store types to match
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DeJeune
commented
Mar 3, 2026
Collaborator
Author
DeJeune
left a comment
There was a problem hiding this comment.
Review Summary
The OperationResult discriminated union and dead field cleanup are clean improvements. The type change is well-applied across main, preload, and renderer store. Good work.
Issues Found
Bug (1):
checkHealth()has an early-return guard (gatewayStatus !== 'running') that makesgetStatus()external gateway detection andstartAndWaitForGateway()health polling dead code. Needs a private probe method without the guard.
Significant (1):
restartGatewayignores the command result and always returns success.
Minor (2):
OperationResultis redeclared in preload asOpenClawOperationResult— consider a shared type.gatewayUrlvisibility/path changes are unrelated to the refactor scope.
Positives
- Discriminated union is the right pattern here — TypeScript narrows cleanly
- All renderer callers already used the correct
!result.successcheck pattern, so no caller changes needed - Dead
uptime/versionfields properly removed across all three layers
Comment on lines
+687
to
+690
| } | ||
| const shellEnv = await getShellEnv() | ||
| await this.execOpenClawCommandWithResult(openclawPath, ['gateway', 'restart'], shellEnv) | ||
| return { success: true } |
Collaborator
Author
There was a problem hiding this comment.
Significant: restartGateway fires gateway restart but ignores the result — if the command fails (non-zero exit or timeout), it still returns { success: true }. Should check the result:
const { code, stderr } = await this.execOpenClawCommandWithResult(openclawPath, ['gateway', 'restart'], shellEnv)
if (code \!== 0) {
this.gatewayStatus = 'error'
return { success: false, message: stderr.trim() || `Restart failed with code ${code}` }
}…, shared type - Extract probeGatewayHealth() without status guard so getStatus() can detect externally-started gateways and startAndWaitForGateway() can poll during 'starting' state - Check restartGateway command exit code instead of always returning success - Move OperationResult to @shared/config/types to avoid duplicate definitions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…install Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the official OpenClaw install scripts (install.sh / install.ps1) instead of manual npm install. The scripts handle Node.js detection, build tools, PATH setup, and diagnostics automatically. - macOS/Linux: curl piped to bash, with sudo-prompt fallback on permission errors - Windows: PowerShell inline execution - Remove China mirror logic (official package includes Chinese support) - Remove SHARP_IGNORE_GLOBAL_LIBVIPS workaround - Refresh shell env in installGatewayService for PATH changes - Drop @qingchencloud/openclaw-zh from uninstall args Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…F-8 encoding - Add copy button to install/uninstall log container header - Make error alerts selectable with select-text class - Fix Windows GBK mojibake by wrapping PowerShell via cmd.exe with chcp 65001 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use buffer mode for execFileSync instead of encoding: 'utf8' to prevent garbled Chinese Windows stderr. Log only exit code on failure instead of the raw error object containing GBK-encoded text. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Include accumulated stderr in logger.error calls when install or uninstall processes exit with non-zero code, enabling better debugging of failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove setShowLogs(false) from checkInstallation to prevent logs from disappearing immediately after install completes - Remove dead lastHealthCheck.version display (field removed from HealthInfo) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e quote stripping Replace cmd.exe /c chcp wrapper with PowerShell-native [Console]::OutputEncoding to set UTF-8 output. cmd.exe was consuming the quotes needed by PowerShell, causing the install script to be echoed instead of executed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ownload Windows PowerShell 5.1 may not enable TLS 1.2 by default, causing Invoke-WebRequest to fail on HTTPS URLs. Prepend SecurityProtocol setting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…install Replace the official install.sh/install.ps1 approach with direct npm install -g openclaw, borrowing key patterns from the scripts: - Auto-install Node.js if missing or version < 22: - macOS: brew install node@22 + brew link - Linux: pacman (Arch) or NodeSource setup_22.x + apt-get/dnf - Windows: winget → choco → scoop fallback chain - Auto-install Git if missing (best-effort, non-blocking) - npm env vars from official scripts: SHARP_IGNORE_GLOBAL_LIBVIPS=1, NPM_CONFIG_SCRIPT_SHELL=cmd.exe (Windows), noise suppression - EACCES retry with sudo-prompt on macOS/Linux - Streaming output to UI throughout all steps This gives us full control over the install flow and avoids the platform-specific issues with the official scripts (cmd.exe quote stripping, TLS, PowerShell execution, mise/fnm detection). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend install() now auto-installs Node.js and Git, so the frontend no longer needs to block installation with warning UI. Install button now proceeds directly to backend which handles everything. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- crossPlatformSpawn: auto-quote command path containing spaces when shell: true on Windows, preventing cmd.exe from splitting the path - Add decodeBufferFromShell(): detect UTF-8 replacement chars and fall back to GBK decoding via iconv-lite for Chinese Windows cmd.exe output - Apply GBK decoding to install/uninstall streaming output - Remove redundant manual quoting in uninstall() (now handled centrally) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add back npmmirror registry for China users (detected via isUserInChina). Use openclaw@latest for all users now that the official package supports Chinese — the separate @qingchencloud/openclaw-zh package is no longer needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handleStartGateway had early returns for syncConfig and startGateway failures that didn't call setIsStarting(false), leaving the button permanently stuck in loading state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The polling loop in startAndWaitForGateway was discarding stderr from checkGatewayStatus and probeGatewayHealth, so timeout errors only showed "Gateway failed to start within 30000ms" instead of the real reason (e.g., "gateway closed (1006 abnormal closure)"). Now captures the last error from polling attempts and appends it to the timeout message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ervice The system service/daemon registered by `openclaw gateway install` does not inherit the OPENCLAW_CONFIG_PATH env var, so it reads the default ~/.openclaw/openclaw.json. Without the auth token there, the gateway starts without auth and health checks fail with 1006 abnormal closure. Now syncProviderConfig() also writes gateway settings (mode, port, auth) to the default openclaw.json, ensuring the system service starts with the correct auth token. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6 tasks
…aming The transform layer was sending the full accumulated `inputBuffer` as the `delta` field in `tool-input-delta` chunks. The renderer then concatenated this already-accumulated string onto `streamingArgs`, causing quadratic memory growth (~N²/2). For a 100KB file write this ballooned to ~5GB, crashing the V8 heap. Fix: send only the incremental `partial_json` fragment (matching how `thinking_delta` already works) and remove the now-unused `inputBuffer` field and `appendToolInputDelta` method from `ClaudeStreamState`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ool streaming" This reverts commit d298009.
Windows scheduled task integration has too many upstream bugs. Skip installGatewayService, uninstallGatewayService, and ensureGatewayServiceInstalled on Windows while keeping gateway start/stop/health/status CLI commands working normally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users with git configured to use SSH (git@github.com:...) may fail during npm install if SSH keys aren't set up. Use GIT_CONFIG env vars to rewrite GitHub SSH URLs to HTTPS within the npm install subprocess. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows without a registered service, `openclaw gateway start` runs in foreground mode and never exits, causing the 20s timeout to kill it. Instead, spawn `openclaw gateway --port <port>` as a detached background process with windowsHide, then poll for readiness as usual. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standardizes gateway startup across platforms by using `gateway start --force` instead of platform-specific detached spawning on Windows. Adds proactive port availability checking before startup to provide clear error messages when the configured port is already in use by another application.
…D heuristic Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The gateway service install already embeds OPENCLAW_CONFIG_PATH into the launchd/systemd service definition, so the daemon reads the correct cherry config file directly. No need to sync back to the default openclaw.json. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.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.
What this PR does
Refactors OpenClawService to delegate gateway lifecycle to the OS service manager (launchd/systemd) via OpenClaw CLI commands, with platform-specific handling for Windows.
Core changes:
openclaw gateway install/start/stop/restart/status/healthCLI commandsChildProcessmanagement,node:netSocket probing, andkillProcesshelperopenclaw gateway healthCLI commandgetStatusis now async and probes health to detect externally-started gatewaysOperationResult = { success: true } | { success: false; message: string }Windows-specific handling:
gateway install/uninstall(scheduled task integration has upstream bugs)openclaw gateway start --force(same as macOS/Linux, but without service registration)NPM_CONFIG_SCRIPT_SHELL=cmd.exefor npm install compatibilityInstall improvements:
GIT_CONFIGenv vars) to avoid SSH key failuresUI improvements:
Why we need it and why it was done in this way
Breaking changes
None. Internal refactoring only — no user-facing API changes.
Special notes for your reviewer
gateway install/uninstallskipped via!isWinguards), gateway started withgateway start --force, port checked before startupgateway installafter npm install,ensureGatewayServiceInstalledon startup,uninstallGatewayServicebefore npm uninstall)openclaw.cherry.jsonand defaultopenclaw.jsonso system services can read itOperationResultis a proper discriminated union in@shared/config/typesChecklist
Release note