Users have reported confusion about "when will ClawPanel update its
gateway protocol to v4". This is actually a misreading: ClawPanel v0.15+
already advertises `minProtocol=3, maxProtocol=4` in its connect frame,
and negotiates v4 transparently when the kernel is >= 2026.5.12. The
`v3|` prefix users were seeing in dev-api.js is the device signature
payload string schema version, which is a completely separate concept
from the handshake protocol version.
Make this visible and unambiguous:
UI
- Add a "Proto v4" badge next to the Gateway service name in
/services once the WS handshake succeeds, with a tooltip explaining
that this is the WS handshake protocol version (not the device
signature payload v3 format).
- Add the same protocol info to the WebSocket row in /chat-debug.
API
- WsClient now exposes `negotiatedProtocol` which prefers the explicit
field from the hello payload (`protocol` / `protocolVersion` /
`negotiatedProtocol`) and falls back to inferring from serverVersion:
kernels >= 2026.5.12 are reported as v4, older as v3. This matches
the panel's advertised range of [3, 4].
- KernelSnapshot grows a `protocol` field so feature gates and UIs that
already consume the snapshot can read it without touching wsClient.
Comments
- Expand the KERNEL_TARGET comment in feature-catalog.js to spell out
the two-distinct-version-numbers rule explicitly.
- Add matching clarifying comments next to the `v3|...` payload string
in both scripts/dev-api.js and src-tauri/src/commands/device.rs, so
the next reader does not confuse payload schema with handshake.
## Verification
- node --check on all touched JS files
- npm run build
- cargo fmt --check && cargo check (clippy errors that surface are
pre-existing debt in config.rs, untouched here)
- Playwright /services: mock wsClient state, observe `协议 v4` badge
rendered with `rgba(99, 102, 241, 0.1)` background and accent color,
for both the explicit-protocol path and the version-inferred path.
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
The runtime locale JSON bundles still contained the older About/Services policy copy even after the module-level strings were updated, so the About page could continue to show the old "recommended only" message in Chinese.
This syncs the zh-CN/en locale bundles with the latest-upstream upgrade copy and mirrors the suffixed OpenClaw version comparison fix in the Web dev API.
## Verification
- npm run build
- node --check scripts/dev-api.js
- cargo check
- 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.
Wire the new Rust `hermes_list_providers` command into the frontend and
replace the hardcoded OpenClaw PROVIDER_PRESETS usage with the
authoritative Hermes registry. Closes the G4 gap from the v3 design.
New module `src/engines/hermes/lib/providers.js`:
- Async `loadHermesProviders()` with per-session cache.
- `groupProviders()` buckets by authType + region: apiKeyIntl,
apiKeyCn, aggregators, oauth, externalProc, custom.
- Lookup helpers: `findProviderById`, `inferProviderByBaseUrl`,
`defaultModelFor`, plus cache reset for hot-reload scenarios.
- Exported auth_type / transport string constants mirroring Rust.
Refactored `src/engines/hermes/pages/setup.js`:
- Drops `PROVIDER_PRESETS` import; loads registry before first paint.
- Provider buttons are grouped under labeled sections (International,
China, Aggregators), with an OAuth hint block listing the CLI
commands users must run (e.g. `hermes auth login nous`).
- Selected provider detail panel now shows target env var
(`ANTHROPIC_API_KEY`, `DEEPSEEK_API_KEY`, etc.) and model catalog
size.
- `doSaveConfig` sends the provider id (not preset key) through
`api.configureHermes`; falls back to `custom` when the base URL
doesn't match any registered provider.
- `doFetchModels` maps provider.transport → apiType.
- Graceful fallback: when the registry is empty (Web mode), UI
degrades to manual Base URL + API Key entry.
Refactored `src/engines/hermes/pages/dashboard.js`:
- Loads provider registry in parallel with gateway refresh.
- Preset buttons filter out the `custom` placeholder and source
data from the async-loaded list.
- Uses `inferProviderByBaseUrl` consistently for highlight / fetch /
save flows.
Frontend API wiring:
- `src/lib/tauri-api.js`:
- Added `hermesListProviders` (10-minute cache).
- Extended `hermesFetchModels` and `hermesUpdateModel` with
optional `provider` param.
- `scripts/dev-api.js`:
- `hermes_list_providers`: Web-mode stub returning [] (triggers
frontend fallback UI).
- `hermes_fetch_models` / `hermes_update_model` accept provider
param (no-op in fetch; full YAML rewrite in update_model matching
Rust behavior).
Verified: `npm run build` green (1.04s). Setup chunk 24.34 kB,
dashboard chunk 24.30 kB. No new warnings.
* 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
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
feat: SkillHub skill store (SDK-based, no CLI dependency)
- Rust SDK (skillhub.rs): HTTP search, index fetch, zip download+extract
- Node.js SDK (skillhub-sdk.js): mirrors Rust SDK for Web/Docker mode
- Skills page: new "Store" tab with full index browse + client-side filter
- Remove 6 old CLI-dependent commands, add 3 SDK commands
- Migrate assistant.js skill tools from ClawHub CLI to SkillHub SDK
- Fix index decode error ({total,skills} wrapper vs bare array)
- Fix skill name display (API field 'name' vs 'display_name')
- Clean up 13 dead CSS rules from old skills hero/tips UI