The previous implementation passed CREATE_NEW_CONSOLE to a Rust
StdCommand spawning cmd.exe directly, but Rust's default Stdio::inherit
copies the parent stdio handles into STARTUPINFO with
STARTF_USESTDHANDLES, which neutralizes CREATE_NEW_CONSOLE. The cmd
process then ran without a visible window (MainWindowHandle = 0), so
users only saw the OpenClaw node child started by runner.cmd in Task
Manager and got the impression that "the terminal does not pop up".
Wrap the launch in `cmd /c start "OpenClaw Gateway" /D <dir> cmd /D /K
runner.cmd` so the new console is created by the `start` builtin via a
fresh CreateProcess call without inherited stdio. The outer cmd /c
itself is short-lived and uses CREATE_NO_WINDOW so it does not flash a
window, and the inner cmd hosting runner.cmd reliably becomes a normal
visible terminal that the user can close to stop Gateway.
Because the visible terminal is now detached from our process tree,
spawn().id() can no longer be tracked. Instead, poll netstat after the
launch and record the listener PID as the active Gateway PID, which is
what the stop path actually needs to send a precise kill to.
## Verification
- cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check
- cargo check --manifest-path src-tauri/Cargo.toml
Add a model client import flow that scans local Codex, Claude Code, Gemini CLI, and common environment variable configurations without reading or copying OAuth tokens.
The new backend command returns safe import candidates with provider metadata, model IDs, and API key environment-variable references. Tauri and Web/dev-api both implement the scanner, and Web mode keeps the scan local even when a remote instance is active.
The Models page now offers an import wizard that lets users select importable candidates, adds providers without overwriting existing keys, preserves secrets as ${ENV_VAR} references, and leaves OAuth-only Codex entries as guidance rather than direct OpenClaw imports.
## Verification
- node --check src/pages/models.js
- node --check src/lib/tauri-api.js
- node --check src/locales/modules/models.js
- node --check scripts/dev-api.js
- cargo fmt --check
- cargo check
- npm run build
Use a generated clawpanel-gateway.cmd runner for the visible Windows Gateway terminal instead of embedding the resolved CLI path directly in the cmd /K command string. This keeps the simple visible-terminal model while improving quoting behavior for standalone, npm shim, and .js CLI paths.
## Verification
- cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check
- cargo check --manifest-path src-tauri/Cargo.toml
- cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings
- npm run build
Windows users can now start OpenClaw Gateway in a normal terminal window instead of relying on a hidden background process. Keeping the terminal open keeps Gateway running; closing it stops Gateway.
The backend guardian also treats a closed Windows Gateway terminal as an intentional stop, so it will not immediately pop a new terminal back up after the user closes it. macOS and Linux keep their existing startup behavior.
## Verification
- cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check
- cargo check --manifest-path src-tauri/Cargo.toml
- cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings
- npm run build
OpenClaw Chinese edition has advanced to 2026.5.12-zh.2 while the panel still recommended 2026.5.12-zh.1 and treated same-base zh patch versions as equivalent.
This updates the recommended Chinese kernel target and makes the version comparison detect suffix-level upgrades such as zh.1 -> zh.2 when both sides expose suffixes. It also adds explicit latest-upstream upgrade actions on the Services and About version cards so users can upgrade to the latest detected upstream version without going through the manual version picker.
## Changes
- update OpenClaw Chinese recommended target to 2026.5.12-zh.2
- detect same-base suffixed patch upgrades in version info
- add Services page "upgrade to latest" action and confirmation copy
- add About page latest-upstream action
## Verification
- npm run build
- cargo check
When the user switches model via the model picker, hermes_update_model rewrites
model.default and model.provider in config.yaml but historically left model.context_length
untouched. The Hermes kernel (8ac351407, May 2026) now actively clears that field on
model switch because the previous model's context window almost never matches the new
model — leaving the stale value caused 'context too large' errors and silently truncated
output. Mirror the upstream behavior by dropping the context_length line as we walk the
model: block, so Hermes falls back to the new model's default window.
Hermes core 1e01b25e7 (May 2026) renamed the display label across the model picker / wizard / status output but kept the provider slug 'alibaba' and the DASHSCOPE_* env vars unchanged. Mirror the label here so the picker label in ClawPanel matches what users see in the Hermes TUI/CLI; existing configs are not migrated because slug and env vars are stable.
- Detect git/network failure patterns (failed to connect, could not resolve host,
unable to access, etc.) in install/update output and append a clear hint
pointing users to the proxy or mirror settings instead of leaving them with
raw multi-line git stderr.
- Add optional 'Hermes Install Mirror' setting (panelConfig.gitMirror): when set,
install/upgrade injects GIT_CONFIG_COUNT/KEY_0/VALUE_0 to rewrite
https://github.com/ via the mirror prefix at process scope only — the user's
global ~/.gitconfig is never touched.
- Surface the new mirror field in Settings (works for both engines), with
zh-CN/en/zh-TW copy and a hint explaining how it interacts with the install
flow.
- /v1/responses ignores body.session_id and generates a fresh server-side
session for each request, causing the Hermes sessions list to grow by
one entry per ClawPanel message.
- /v1/runs honors body.session_id directly, so reversing the call priority
(try /v1/runs first; fall back to /v1/responses on HTTP 404 for older
Hermes Agent builds) lets sessions group naturally without breaking
backward compatibility.
Close the G7 gap from the v3 integration design.
Scenario: A user upgrades Hermes (or manually edits config.yaml and drops
the api_server platform block). The next `gateway start` silently produces
a Gateway that doesn't expose /v1/runs, and ClawPanel's chat/agent flows
fail with confusing errors.
Solution: Run a pre-start guardian that checks
`platforms.api_server.enabled: true` and auto-heals the file when
missing, with a timestamped backup so users can always roll back.
Backend (src-tauri/src/commands/hermes.rs):
- New pure helpers `config_has_api_server_enabled(raw)` and
`patch_yaml_ensure_api_server(raw)` working directly on YAML strings
(no serde_yaml dependency needed — we only touch 3 structural keys).
- `ensure_api_server_enabled(app)` wraps the helpers with filesystem
I/O: reads config.yaml, writes `config.yaml.bak-<epoch>` on mutation,
writes the patched content back, emits `hermes-config-patched` so
the frontend can show a transparent toast.
- Called from `hermes_gateway_action` on every `start` action. If
config.yaml doesn't exist, the guardian is a no-op (configure_hermes
creates a compliant file on first run).
- 7 new unit tests covering: truthy value variants (true/yes/on/1),
missing/disabled/commented scenarios, no-op when healthy,
appending a full platforms block, injecting into existing platforms,
replacing an explicitly disabled api_server subtree.
Web mode (scripts/dev-api.js):
- Mirrors the three helpers as `_hermesConfigHasApiServerEnabled`,
`_hermesPatchYamlEnsureApiServer`, `_hermesEnsureApiServerEnabled`.
- Called in `hermes_gateway_action` start path.
- Logs to console.warn instead of emitting a Tauri event.
Frontend (src/engines/hermes/pages/dashboard.js):
- Dashboard subscribes to `hermes-config-patched` and surfaces a toast
(6s duration) so the user knows the auto-heal happened and where the
backup lives.
Verified: cargo fmt / cargo clippy -D warnings / cargo test all green
(12 hermes tests pass total: 5 provider registry + 7 guardian).
`node --check scripts/dev-api.js` passes. `npm run build` green.
Users may need to configure custom environment variables for Hermes
(e.g. `TAVILY_API_KEY` for the tavily skill, `HTTP_PROXY`, SKILL_*
settings). Previously the only way to set these was to hand-edit
~/.hermes/.env, which risks clobbering the provider keys that
ClawPanel writes through configure_hermes.
This patch adds a dedicated editor UI backed by three new Tauri
commands that refuse to touch managed keys.
Backend (src-tauri/src/commands/hermes.rs):
- `hermes_env_read_unmanaged` — returns every KEY=VALUE pair whose key
is NOT in `hermes_providers::all_managed_env_keys()` (so provider
API keys, base URLs, `GATEWAY_ALLOW_ALL_USERS`, `API_SERVER_KEY`
stay hidden). Preserves file order, dedups.
- `hermes_env_set(key, value)` — validates key against `^[A-Z0-9_]+$`,
refuses managed keys, updates first occurrence or appends,
preserves comments/blanks.
- `hermes_env_delete(key)` — refuses managed keys, removes first
matching line, preserves other structure.
All three commands registered in `src-tauri/src/lib.rs`.
Frontend:
- New page `src/engines/hermes/pages/env-editor.js`:
- Header with "back to dashboard" link and warning banner listing
which keys are managed by ClawPanel.
- Table with Key / Value / Actions columns.
- Inline edit mode per row (save / cancel).
- "Add variable" button for new entries.
- Value column masks long secrets (`sk-a…xyz9`) so glances don't
leak credentials.
- Toast feedback on save / delete / validation errors.
- Inline Chinese copy (TODO: wire up i18n when the locales module
lands).
- Route registered at `/h/env` in `src/engines/hermes/index.js`.
- Dashboard "Model config" section now has a subtle link
".env 高级编辑 →" pointing to the new page.
API wiring:
- `src/lib/tauri-api.js`: added `hermesEnvReadUnmanaged`,
`hermesEnvSet`, `hermesEnvDelete`.
- `scripts/dev-api.js`: mirrors the three commands in Web mode with
a duplicated managed-key list (keep in sync with Rust's
`hermes_providers::all_managed_env_keys` as new providers land).
Verified: cargo fmt / cargo clippy -D warnings / cargo test / npm run
build all green. Dashboard chunk unchanged (24.30 kB); new env-editor
chunk is ~7 kB gzip.
Introduce an authoritative Hermes provider registry in Rust, mirroring
upstream `hermes-agent` data (PROVIDER_REGISTRY + _PROVIDER_MODELS), and
refactor the four critical Hermes commands to be provider-aware.
Closes the G1/G2/G3 blockers identified in the v3 integration design.
New module `src-tauri/src/commands/hermes_providers.rs`:
- Static catalog of 22 providers: 17 api_key (incl. DeepSeek, Gemini,
xAI, GLM/Z.AI, Kimi, MiniMax int'l + CN, Alibaba DashScope, Xiaomi,
Copilot PAT, HuggingFace, OpenRouter, Vercel AI Gateway, OpenCode
Zen/Go, Kilocode), 3 OAuth (Nous, OpenAI Codex, Qwen OAuth), 1
external_process (Copilot ACP), and `custom` placeholder.
- Each entry carries id, display name, auth_type, base_url, env var
priority list, transport, probe strategy, known models, aggregator
flag, and CLI auth hint.
- Helpers: `get_provider`, `primary_api_key_env`, `primary_base_url_env`,
`all_managed_env_keys`, `infer_provider_from_env_keys`,
`find_provider_by_model`.
- New Tauri command `hermes_list_providers` (cached client-side).
- 5 unit tests covering registry integrity and lookup semantics.
Refactored `src-tauri/src/commands/hermes.rs`:
- `configure_hermes`: writes `model.provider` in config.yaml and routes
API keys through the registry's `api_key_env_vars`. Skips key write
for OAuth providers (Hermes CLI manages auth.json itself). Clears
all managed keys on provider switch to avoid stale credentials.
- `hermes_read_config`: reads `model.provider`, then reverse-looks up
the matching API key from the registry's env var priority list.
Falls back to inferring provider from .env when config.yaml omits
the provider field.
- `hermes_update_model`: accepts optional `provider` param; writes
`model.provider` line into config.yaml (adds it when missing, updates
in place when present, removes it for `custom`).
- `hermes_fetch_models`: accepts optional `provider` param; uses
registry's probe strategy (`PROBE_NONE` returns static catalog for
OAuth providers instead of hitting the API).
Registration:
- `src-tauri/src/commands/mod.rs`: declare `hermes_providers` module.
- `src-tauri/src/lib.rs`: import + register `hermes_list_providers`.
Verified: cargo fmt / cargo clippy -D warnings / cargo test all green
(5 new unit tests pass).
* feat(diagnose): detect and inform about @homebridge/ciao cmd popup bug
On Windows, OpenClaw's transitive dependency @homebridge/ciao (<=1.3.6)
calls child_process.exec('arp -a ...') every 15-30 seconds without
passing windowsHide:true, causing a cmd.exe popup to flash.
This is an upstream library bug:
- Issue: homebridge/ciao#64
- PR: homebridge/ciao#65 (open, not merged)
ClawPanel deliberately chooses 'detect and inform' rather than silently
patching the user's node_modules. We respect the user's control over
their own machine.
Changes:
- src-tauri/src/commands/diagnose.rs: new check_ciao_windowshide_bug
command; scans openclaw's @homebridge/ciao/lib/NetworkManager.js and
reports whether the buggy exec pattern is present
- src-tauri/src/lib.rs: register the new command
- scripts/dev-api.js: Web-mode stub (returns affected:false since the
bug does not manifest off-Windows)
- src/lib/tauri-api.js: add api.checkCiaoWindowsHideBug
- src/lib/ciao-bug-warning.js: new module with toast + modal flow,
version-scoped dismiss (localStorage)
- src/locales/modules/ciaoBug.js: translations in 5 primary languages
- src/locales/index.js: register the ciaoBug module
- src/main.js: call checker 3s after splash hides
Non-Windows users see nothing; Windows users see a single warning toast
(version-dismissible) linking to three fix paths: wait for upstream,
apply patch-package, or edit NetworkManager.js manually.
* fix(diagnose): gate helper with cfg(windows), drop unneeded return
CI failures on Linux + macOS:
- openclaw_module_root was dead code when target_os != windows
since the only caller is the #[cfg(target_os = "windows")] block
inside check_ciao_windowshide_bug
- Explicit `return CiaoCheckResult {...};` in the non-Windows branch
triggered clippy::needless_return
Fix:
- Add #[cfg(target_os = "windows")] to openclaw_module_root so it
is not compiled on other platforms
- Convert the non-Windows early exit to a tail expression
Fix for #244 Hidden-start repeat loop:
cleanup_zombie_gateway_processes used a single /health probe to
decide whether a port-listening process is a zombie. When Gateway
reaches 'ready' but is still initializing (loading plugins, connecting
channels, warming up networks), a single probe can time out -> the
healthy Gateway gets killed -> start_service_impl Hidden-starts a new
one -> loop.
Add is_gateway_port_responsive_with_retry: 3 attempts with 800ms
interval before classifying as zombie. Maximum wait 2.4s for a
process that's genuinely healthy to show up as such.
Effect: healthy Gateway no longer misidentified during warm-up,
Hidden-start no longer triggered on an already-ready Gateway.
Refs #244
Root cause for #243 / #244 / #240: model edits trigger
api.restartGateway() with only 300ms debounce. Fast consecutive
edits stack up restart calls, creating zombie Gateway processes,
failed restarts, and CPU fan spikes.
Layer A (frontend):
- New src/lib/gateway-restart-queue.js: 3s debounce + single-flight
lock + reschedule on in-flight request
- Refactor src/pages/models.js doAutoSave: write config immediately,
schedule restart via queue with 'Apply now' toast button
- Subscribe to queue state for unified success/failure toast
- Add i18n: models.configQueued, models.applyNow
Layer B (backend):
- src-tauri/src/commands/config.rs: wrap restart_gateway /
reload_gateway with tokio::sync::Mutex + 2s cooldown
- Cargo.toml: add tokio 'sync' feature
- scripts/dev-api.js: same guard for Web mode (inflight promise
reuse + 2s cooldown)
Effects:
- 10 rapid edits within 3s -> 1 restart (was 10+ with races)
- Backend serializes concurrent restart calls, no zombie spawns
- User sees single 'Apply now' toast instead of restart storm
Refs #243#244#240