Commit Graph

207 Commits

Author SHA1 Message Date
晴天
bc55cf4829 fix(channels): 同步契约按内核源码逐条核对并修正
对照 OpenClaw(zod-schema.core.ts / model-ref-shared.ts)与 Hermes
(config.py / auth.py / model_normalize.py)内核源码验证同步写入契约,
修正三处不一致:

- OpenClaw 模型条目恒写含 id/name 的完整对象(内核 strict schema
  两字段必填,裸字符串有被拒风险),name 缺省回退为模型 ID;
  模型引用按第一个 / 切分已确认正确,含斜杠模型 ID 无需处理
- Hermes model.default 改写纯模型 ID:内核不解析 "provider/model"
  前缀(provider 由 model.provider 单独指定),原先拼接前缀会写出
  内核不认识的模型名
- Hermes 回退 provider 按注册表真实 id 匹配:OpenAI 兼容 → 'custom'
  (注册表无独立 'openai' API-Key id),Gemini → 'gemini'(内核经
  OpenAI 兼容端点接入,按 transport 匹配会误判为不支持);
  自定义 Base URL 仅对 OpenAI 兼容渠道写入,避免破坏 anthropic/gemini
  的专用端点格式

另:渠道编辑器新增「可同步到」实时适配提示(切换 API 类型即显示
OpenClaw / Hermes / 助手的支持情况);测试断言更新为核对后的契约
(428 通过)。发现的存量问题已记录:最新内核 api 枚举中
openai-codex-responses 已改名,共享 API_TYPES 需对照推荐稳定版处理。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 12:44:41 -07:00
晴天
79863ffddd feat(channels): 模型配置入口收口到模型渠道页,渠道卡片强化绑定状态
模型配置此前散落三处、口径不一。本次把模型渠道页确立为配置中枢:

- OpenClaw 模型配置页顶部新增引导条:推荐在模型渠道统一维护并同步
- Hermes 安装向导配置步新增引导:已有渠道可从渠道页一键同步到 Hermes
- 晴辰助手 API 设置新增引导:已有渠道可直接同步到助手,无需重复填写
- 渠道卡片同步区新增「绑定状态」标题,OpenClaw / Hermes / 助手三行
  绑定关系(已同步 / 有未同步变更 / 未同步 / 不支持)一目了然

i18n:models / assistant / engine / modelChannels 四个模块补充
简中 / 繁中 / 英文案。验证:npm build + node --test 427 通过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 12:32:31 -07:00
晴天
8a247af03e fix(setup): 未安装状态不再反复跳回检测页、聚焦重检不再清空页面
用户反馈"未安装时系统一直在检测/跳回检测页",三个成因逐一修复:

- 安装/升级任务事件(upgrade-done/error)回调在 OpenClaw 未就绪时
  无条件 navigate('/setup'):安装失败会把用户从诊断/设置页拽回安装页,
  已在 setup 页时重复 navigate 还会整页重建重新检测。
  现只把默认路由指向 setup,仅当停留在依赖 CLI 的仪表盘时才主动跳转
- 窗口聚焦触发的重检(#Compat-4)每次都把步骤区清成骨架屏,
  切窗口回来就像"又从头检测"。聚焦重检改为 silent 模式:
  保留已渲染内容,检测完成后原地更新
- 检测流程加异常兜底:任何错误渲染错误卡片并提示重新检测,
  骨架屏不再有机会永久残留

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 12:14:16 -07:00
晴天
1dc9151b63 feat(hermes): 安装向导体验重做——实时日志、镜像配置、可操作错误与断点续行
依据上游 Hermes 源码(官方 install.sh/ps1 → uv → setup → doctor 流程)
与面板安装链路审计(18 项问题清单,见 .tmp 调研文档)实施:

- 安装输出实时流式:新增 run_install_command_streaming,uv tool/pip
  安装的 stdout/stderr 逐行实时 emit(原 wait_with_output 等进程结束
  才发日志,用户盯 3-10 分钟转圈);stderr 保留尾部 8KB 供失败诊断
- 网络与镜像 UI:安装步新增折叠区,PyPI 镜像(清华/阿里云/自定义)
  与 Git 镜像前缀直接在向导内配置并持久化(panelConfig,后端已读取)
- 失败诊断可操作:诊断关键词覆盖 PyPI 超时/SSL/代理/解析失败,
  给出镜像与代理建议;uv pip 备选安装路径同样接入诊断
- 检测门控:环境有提示项(Python 版本/Git 缺失)时停留检测页等确认,
  不再 800ms 自动跳走;全部正常仍自动进入下一步
- 断点续行:向导阶段写入 sessionStorage,重开回到上次步骤
  (以检测结果为前提校验,complete 不恢复)
- 配置步错误改内联面板,API Key 旁提示「获取模型列表」可验证 Key;
  自定义网关健康检查对 ok=false 响应视为失败

另修复模型渠道页 API 类型下拉显示 [object Object](API_TYPES 为
{value,label} 对象数组),卡片芯片同步显示可读类型名。

验证:npm build / node --test 427 通过 / cargo fmt+clippy -D warnings /
cargo test --lib 314 通过

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 12:07:40 -07:00
晴天
dba69ee0fc feat(channels): 统一模型渠道——一处配置,同步 OpenClaw / Hermes / 晴辰助手
新增「模型渠道」页面(通用分组):用户只维护一份渠道配置
(服务商预设 / Base URL / API Key / 模型列表 / 默认模型),
通过显式同步推送到三个消费方,消灭重复配置。

实现要点:
- 渠道存储 src-tauri/src/commands/model_channels.rs:
  读取只回掩码(apiKeySaved/apiKeyMask),写入支持 __KEEP__ 哨兵保留旧 Key,
  明文 Key 仅经 reveal_model_channel_key 在同步时取出;
  文件位于 openclaw 数据目录下,便携迁移自动带走;含 6 个单元测试
- 同步逻辑 src/lib/model-channels.js 组合现有命令完成(各自带自动备份):
  OpenClaw 只 upsert 对应 provider 保留未知字段;
  Hermes 写 provider 环境变量 + 可选默认模型(仅 OpenAI/Anthropic/Gemini
  兼容 API Key 型,OAuth/SDK 型仍走 Hermes 向导);
  助手为一次性拷贝到 localStorage
- 页面 src/pages/model-channels.js:渠道卡片 + 三目标同步状态徽标
  (已同步/有未同步变更/未同步)+ 编辑弹窗(预设自动填充、在线拉取模型、
  默认模型联动)+ 从 OpenClaw 现有配置一键导入 + 全部操作确认弹窗
- Web 模式 dev-api.js 同构 handler + ALWAYS_LOCAL;i18n 简/繁/英 +
  侧栏 11 语言;tests/model-channels.test.js 锁定注册链与安全约束

验证:npm build / cargo fmt+check+clippy -D warnings / cargo test --lib
314 通过 / node --test 全部 427 通过

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 11:48:24 -07:00
晴天
b04deb4e54 fix(release): 0.18.6 收口——审查修复、创作中心与便携迁移加固、设置页提速
按全量代码审查(8 角度 × 对抗验证)修复 10 项确认问题并完成收口:

安全:
- 媒体资产下载仅对与服务商 Base URL 同主机的地址携带 API Key,防止密钥外泄
- 助手媒体工具默认关闭需显式开启;付费图片/视频生成在任何模式下强制确认

数据与容错:
- 媒体数据统一存放 openclaw 数据目录下,便携迁移后配置与历史直接生效
- 视频轮询 429/5xx 瞬时错误不再永久标记失败;失败任务可重新轮询找回
- 创建视频任务无法识别任务 ID 时保留任务记录与原始响应(可能已计费)
- 便携迁移失败时正确显示错误状态;便携命令加入 Web 模式 ALWAYS_LOCAL

性能与体验:
- 任务记录落盘前裁剪 base64 等超大字段,媒体历史文件不再膨胀
- 资产预览 stat 预检 + 64MB 上限 + 缓存淘汰;轮询并行化(后端 jobs 加锁)
- 初始设置页两阶段渲染:本地检测先出首屏,版本网络查询异步补充
- 创作中心删除改用统一确认弹窗(原生 confirm 在 macOS WebView 失效)
- 检查配置/获取模型列表放行 http:// 自建网关;桌面/Web 状态解析对齐
- 统一三处路径包含检查为 utils 共享 helper(Linux 大小写误判修复)
- 补充便携模式 hermes-cli-missing 警告翻译(简/繁/英)

其他:修复 web-headless-reload-policy 陈旧断言(e16ff2b 后 ws-client 已无隐式 reload)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 11:43:33 -07:00
晴天
675ad1628b fix(openclaw): 兼容新版配置与 Node 门槛 2026-06-11 15:24:01 +08:00
晴天
d60db3b71b fix(setup): 补齐跨端 Node 检测与新手引导 2026-06-08 22:31:00 +08:00
晴天
634fe66556 fix(setup): 完善 Node 版本检测与升级引导 2026-06-08 22:04:55 +08:00
晴天
e16ff2baee fix(openclaw): stabilize windows install and pairing 2026-06-07 03:28:10 +08:00
晴天
de1531d111 feat: prepare v0.18.0 release 2026-06-06 18:32:37 +08:00
晴天
f340b64028 feat(update): integrate official site update flow 2026-06-06 13:59:52 +08:00
cursor[bot]
8568dd0d2a fix(dashboard): prevent superseded dashboard loads from mutating state (#301)
Adds two loadSeq guards in _loadDashboardDataInner: after the first await coreP and before the self-heal writeOpenclawConfig path. Prevents stale loads from polluting cache, popping toasts, or writing config after a newer load has been queued.
2026-05-28 07:27:51 +08:00
晴天
b3d763c46a fix(channels): improve configured card touch targets 2026-05-24 02:29:29 +08:00
晴天
7b32b533fb feat(channels): add Tlon config compatibility 2026-05-24 02:03:55 +08:00
晴天
7e3bb71fca feat(channels): add IRC config compatibility 2026-05-24 00:57:37 +08:00
晴天
326c5597df feat(channels): add Nostr config compatibility 2026-05-23 09:25:07 +08:00
晴天
dcc3751ded feat(channels): add Twitch config compatibility 2026-05-23 08:42:54 +08:00
晴天
8623efd49c feat(channels): add Nextcloud Talk config compatibility 2026-05-23 08:25:34 +08:00
晴天
579d706075 feat(channels): add ClickClack config compatibility 2026-05-23 08:07:39 +08:00
晴天
d933177ec3 feat(channels): restore WhatsApp config compatibility 2026-05-23 07:51:16 +08:00
晴天
8d745e7543 feat(channels): add iMessage config compatibility 2026-05-23 07:31:06 +08:00
晴天
6c947a1fec feat(hermes): support Discord plugin runtime config 2026-05-23 06:41:49 +08:00
晴天
f188bb85f7 feat(channels): improve Microsoft Teams config compatibility 2026-05-23 06:22:23 +08:00
晴天
49be118c5f feat(channels): improve Signal config compatibility 2026-05-23 05:56:59 +08:00
晴天
09bc45ae4c feat(channels): add Synology and Google Chat config 2026-05-23 05:37:06 +08:00
晴天
53fe25a277 feat(channels): add LINE and Mattermost config 2026-05-23 05:08:51 +08:00
晴天
780b1bdde5 feat(channels): add Zalo channel configuration 2026-05-23 04:38:49 +08:00
晴天
067389d65f fix(channels): add generic channel diagnostics 2026-05-23 04:14:45 +08:00
晴天
d5d8805c5d fix(channels): expose Discord guild allowlist fields 2026-05-23 03:31:23 +08:00
晴天
e2eee18e05 fix(channels): preserve Discord application id 2026-05-23 03:25:22 +08:00
晴天
01dff38a97 fix(channels): save multi-account platform configs 2026-05-23 03:06:52 +08:00
晴天
6aa7a05f36 fix(channels): preserve SecretRef credentials 2026-05-23 02:23:52 +08:00
晴天
27b35b6298 fix(channels): normalize OpenClaw channel config policies 2026-05-23 01:14:42 +08:00
晴天
1ae223a0b1 feat(channels): add gateway runtime status 2026-05-23 00:09:46 +08:00
晴天
d0f0d1f6b7 fix(gateway): release 0.16.5 2026-05-22 20:42:16 +08:00
晴天
4d82395b90 fix(engine-select): release 0.16.4 2026-05-22 19:46:07 +08:00
晴天
9d2dc8438e fix: apply pending correctness fixes
Cherry-pick the still-relevant fixes from recent draft PRs without pulling in stale release/docs changes:

- serialize dashboard data loads to avoid concurrent config self-heal writes
- preserve valid per-model default blocks during dashboard model self-heal
- pass structured humanizeError results directly to toast for model import scan failures
- align frontend kernel isLatest with suffix-aware recommended version ordering

Verification:
- node --test tests/*.test.js
- npm run build
2026-05-21 19:06:38 +08:00
晴天
12cc9cd6ce fix(assistant): give assistant a Hermes identity, surface raw install hint, unblock CI
Three follow-ups the user spotted in one round.

assistant.js — assistant did not know it was on Hermes
  Both engines (OpenClaw and Hermes Agent) reuse the same /assistant
  page (engines/hermes/index.js comments it as "共用页面/引擎无关"),
  but getSystemPromptBase() hard-coded the OpenClaw self-introduction:
  "你帮助用户管理和排障 OpenClaw AI Agent 平台 / 你精通 OpenClaw 的架
  构…", followed by a CLI cheatsheet for `openclaw gateway start` and
  `openclaw config apply`. Result: under the Hermes engine, the
  assistant happily told users to run `openclaw doctor` and edit
  `~/.openclaw/openclaw.json` — neither of which exists in the Hermes
  world.

  Split into a per-engine dispatcher:
    getSystemPromptBase()
      └ if hermes  → getHermesSystemPromptBase()  (new)
      └ else       → getOpenclawSystemPromptBase() (renamed, same body)

  The new Hermes base prompt covers the facts that actually matter:
   - dual-process layout: Gateway 8642 (chat API, what ClawPanel
     mostly drives) vs Dashboard 9119 (admin/profiles/skills/oauth/
     kanban — must be started separately)
   - Profile system (independent workspaces, switchProfile restarts
     dashboard, multi-gateway view)
   - lazy_deps allowlist and why pre-installing matters
   - paths: ~/.hermes (data) and ~/.hermes-venv (interpreter), with a
     reminder that ~/.openclaw/clawpanel.json is the panel config
     shared with the OpenClaw engine — not Hermes data
   - Top-5 problem playbook (9119 not running, venv missing, channels
     hanging on first launch, gateway crashing, profile drift)
   - Explicit "do not give the user `openclaw …` commands"

  Two more spots in buildSystemPrompt() are also engine-aware now:
   - the "ClawPanel 工具能力" bullet list inside the soul-cache branch
   - the "跨平台路径" reminder (Hermes points to .hermes / .hermes-venv)

lazy-deps.js — "请确认目标资源是否仍存在" was masking the real hint
  When the user has not installed Hermes yet, Rust's
  `hermes_lazy_deps_features` returns the very actionable string
  "Hermes venv 未找到(~/.hermes-venv 不存在)。请先安装 Hermes。".
  humanize-error.js then sees "未找到", classifies the error as
  notFound, and replaces the message with the generic template
  "请确认目标资源是否仍存在" — which tells the user nothing about
  installing Hermes.

  Take humanizeError() but render `message + raw` instead of
  `message + hint`. The user now sees both the friendly title and the
  exact Rust-side instruction. Drop the unused humanizeErrorText
  import that this commit replaces.

config.rs — unblock CI (clippy too_many_arguments on existing code)
  The clippy gate has been red on main since e1eda2d ("import external
  client configs") because two helpers in commands/config.rs take >7
  positional parameters:
    - push_client_candidate (14 params)
    - scan_json_client_file (10 params)

  Both helpers exist purely to push a flat record into a Vec<Value>.
  Wrapping them in a struct just to satisfy clippy would force every
  caller to first build that struct, hurting readability. Suppress
  clippy::too_many_arguments locally on these two functions with an
  inline comment explaining why.

## Verification
- node --check + npm run build: clean
- cargo clippy --all-targets -- -D warnings: now compiles to
  "Finished `dev` profile" with zero errors/warnings (previously
  failed with two too_many_arguments)
- Playwright: import lazy-deps with api.hermesLazyDepsFeatures mocked
  to throw "Hermes venv 未找到 … 请先安装 Hermes。", rendered content
  contains "请先安装 Hermes" (hasRaw=true), does not contain the
  generic "请确认目标资源是否仍存在" (hasGenericNotFound=false), and
  does not contain "[object Object]"
2026-05-16 14:24:45 +08:00
晴天
4b0d8e5042 fix(ui): hide useless docker manager on desktop, auto-start hermes dashboard, polish layout
Four independent UI fixes the user spotted in one screenshot tour:

services.js — desktop docker manager
  ClawPanel is not a docker management tool. The "Docker 多实例管理"
  block on the OpenClaw services page only makes sense for users who
  deployed ClawPanel itself in Web mode (serve.js / dev-api) and want
  to orchestrate multiple OpenClaw containers from one panel.

  On desktop Tauri this block always degrades to either "未启用" with
  a connect ENOENT error (no docker daemon on the user box) or to a
  generic "unavailable" placeholder — pure visual noise. Skip the
  whole config-section in render() and bail out of loadDockerManager()
  when isTauriRuntime() is true. Web mode keeps the feature.

profiles.js — Hermes Profile manager could not load
  Profile API only exists on the Hermes Dashboard process at 9119,
  which the user has to start by hand. When it is offline, the page
  showed a raw "由于目标计算机积极拒绝, 无法连接 (10061)" error which
  is useless: users do not know they need to start a separate process.

  load() now does the same probe → auto-start dance that
  extensions.js / dashboard.js use for their 9119 links: probe first,
  call hermesDashboardStart() if not running, only then issue the
  /api/profiles request. If the start itself fails, we fall through to
  the original catch and humanize-error renders a real reason.

lazy-deps.js — "[object Object]" on load failure
  humanizeError() returns { message, hint, raw, action? }, not a
  string. The catch branch passed the object straight into
  escapeHtml(), so String(obj) coerced to "[object Object]". Switch
  to humanizeErrorText() which is exactly the (message + hint)
  one-liner string variant.

layout.css — header buttons crammed against the description
  Several pages (hermes profiles / lazy-deps / files / gateways /
  group-chat / kanban / oauth) put their header buttons inside
  <div class="config-actions"> nested in <div class="page-header">,
  but the existing flex layout rule only matched .page-actions. The
  buttons therefore stacked directly under .page-desc with zero
  visible gap. Add .config-actions to both the desktop flex selector
  and the @media (max-width:768px) column-stack selector so all
  these pages get the same title-left / actions-right layout.

## Verification
- npm run build (no warnings beyond the existing chunk size note)
- Playwright on /services in browser mode: docker section present;
  same page after mocking window.__TAURI_INTERNALS__: section gone
- Playwright on /lazy-deps: rendered content does not contain the
  string "[object Object]"
- Playwright dynamic-imports profiles / lazy-deps / files render():
  computed style on .page-header is display:flex, flex-direction:row,
  title and button share the same getBoundingClientRect().top, button
  pushed to the right edge (justify-content:space-between effective)
2026-05-16 13:46:24 +08:00
晴天
7d75486a53 feat(gateway): surface negotiated handshake protocol version in UI
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.
2026-05-16 13:02:08 +08:00
晴天
a13c9ee6ba fix(models): stop auto-filling fallback chain and add clear-all button
The fallback editor's "Add" buttons appeared to do nothing because
applyDefaultModel auto-populated defaults.model.fallbacks with every
non-primary model whenever the list was empty (and the same for
defaults.models). After any save with an empty chain, the chain got
filled with all 17+ candidates; the candidate pool became "No candidate
models available" and any subsequent Add click hit the early return
`if (modelConfig.fallbacks.includes(full)) return`.

Even worse, the auto-fill made it impossible for users to keep an empty
fallback chain on purpose: deleting all chips would silently get
replaced with every model on the next debounced autosave.

Remove the auto-fill in applyDefaultModel. An empty fallback chain is a
valid configuration that means "no implicit fallback"; Gateway already
surfaces a clear primary-model error in that case. normalizeDefaultModel
Selection still cleans up invalid/duplicate entries.

Also add a small "Clear All" button next to the active chain title so
users can drop the entire fallback list in one click instead of removing
chips one by one (especially useful for the existing bloated 17-fallback
state created by the old auto-fill path).

## Verification
- node --check src/pages/models.js
- node --check src/locales/modules/models.js
- npm run build
- Playwright repro: open /#/models → Clear All → fallbacks on disk
  go from 17 → 0 → click Add on one candidate → fallbacks on disk are
  exactly that one entry, no longer auto-expanded back to 17.
2026-05-16 12:07:35 +08:00
晴天
9742786f8c fix(models): normalize invalid primary model 2026-05-16 00:16:39 +08:00
晴天
c318ff3b37 fix(assistant): normalize OpenClaw context path 2026-05-15 23:37:28 +08:00
晴天
e1eda2db55 feat(models): import external client configs
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
2026-05-15 23:18:50 +08:00
晴天
f411386ab5 fix(ui): polish docker and model configuration views
Treat an unavailable local Docker socket with no containers as an optional Docker management capability instead of showing a meaningless offline default node.

Improve the model configuration layout for large model/fallback lists by wrapping controls, truncating long IDs safely, capping collapsed fallback chips, and making the fallback editor responsive.

Guard chat message insertion against route changes so async history/hosted output cannot insert into an unloaded chat DOM.

## Verification
- node --check src/pages/models.js
- node --check src/pages/services.js
- node --check src/pages/chat.js
- node --check src/locales/modules/services.js
- npm run build
2026-05-15 21:01:27 +08:00
晴天
322bf1a0a6 fix(dashboard): avoid startup skeleton deadlock
Delay heavy dashboard requests until after the first stat-card render so slow version checks, agent scans, MCP reads, backups, channel discovery, or log tail reads cannot occupy the backend before the initial paint.

Add a 1.2s first-paint fallback that replaces skeleton cards with safe unknown-state cards and logs a warning when dashboard APIs are still pending.

## Verification
- npm run build
2026-05-15 20:48:14 +08:00
晴天
2f7cd6d429 perf(ui): speed up dashboard startup rendering
Render the dashboard first wave without waiting for get_version_info, which may spawn CLI work and query the registry. Version data now updates the stat cards asynchronously after the core service/config data is shown.

Also shorten the desktop Gateway port probe before WebSocket connection from 20s/2s polling to 3s/300ms polling, relying on the WebSocket reconnect path instead of blocking startup for a long time.

## Verification
- npm run build
2026-05-15 20:15:06 +08:00
晴天
dcafd29e51 fix(openclaw): allow upgrading kernel to latest patch
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
2026-05-15 19:08:42 +08:00
晴天
7f078a3c49 fix(ui): import term tooltip helpers in config pages
Gateway 配置页和模型配置页都会在 label 中渲染术语帮助按钮,并在页面渲染后调用 tooltip 绑定逻辑。

这两个页面之前引用了 termHelpHtml / attachTermTooltips,但没有导入对应 helper,导致 Gateway 配置页加载配置后直接抛出 ReferenceError,页面停在加载失败状态。

## 修复
- Gateway 配置页补充 term-tooltip helper import
- 模型配置页补充同一 helper import,避免进入编辑服务商弹窗时触发同类运行时错误

## 验证
- npm run build:PASS
2026-05-15 18:54:13 +08:00