mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-06-28 03:01:54 +08:00
fix: fake update detection, Hermes web mode commands, cleanup hot update
1. 假更新检测: checkNewVersion 对比 Tauri 二进制版本与前端版本,
若前端版本 > 二进制版本(热更新导致),提示用户下载完整安装包
2. 版本统一: sidebar 和 about 页面均使用 __APP_VERSION__
3. 更新机制: checkHotUpdate → checkNewVersion,改用 GitHub Releases API,
移除 check_frontend_update / download / rollback / get_update_status 死代码
4. Hermes Web 模式: dev-api.js 实现全部 15 个 Hermes 命令处理器
(check_python, check_hermes, install_hermes, configure_hermes,
hermes_gateway_action, hermes_health_check, hermes_api_proxy,
hermes_agent_run, hermes_read_config, hermes_fetch_models,
hermes_update_model, hermes_detect_environments, hermes_set_gateway_url,
update_hermes, uninstall_hermes)
5. i18n: 新增 versionMismatch, hotUpdateDeprecated, downloadFullInstaller
This commit is contained in:
@@ -6,7 +6,7 @@ import { toggleTheme, getTheme } from '../lib/theme.js'
|
||||
import { isOpenclawReady } from '../lib/app-state.js'
|
||||
import { api } from '../lib/tauri-api.js'
|
||||
import { toast } from './toast.js'
|
||||
import { version as APP_VERSION } from '../../package.json'
|
||||
const APP_VERSION = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.0.0'
|
||||
import { t, getLang, setLang, getAvailableLangs } from '../lib/i18n.js'
|
||||
import { isFeatureAvailable } from '../lib/feature-gates.js'
|
||||
import { getActiveEngine, getActiveEngineId, listEngines, switchEngine, onEngineChange } from '../lib/engine-manager.js'
|
||||
|
||||
@@ -86,6 +86,9 @@ export default {
|
||||
downloadFromWebsite: _('官网下载', 'Website Download', '官網下載'),
|
||||
downloadFromGitHub: _('GitHub 下载', 'GitHub Download', 'GitHub 下載'),
|
||||
newVersionAvailable: _('发现新版本 v{version},请前往下载更新', 'New version v{version} available, please download to update', '發現新版本 v{version},請前往下載更新'),
|
||||
versionMismatch: _('前端版本 v{frontend} 与应用版本 v{binary} 不一致', 'Frontend v{frontend} does not match app v{binary}', '前端版本 v{frontend} 與應用版本 v{binary} 不一致', 'フロントエンド v{frontend} とアプリ v{binary} が一致しません', '프런트엔드 v{frontend}과 앱 v{binary}이 일치하지 않습니다'),
|
||||
hotUpdateDeprecated: _('热更新已弃用,请下载完整安装包以获得最佳体验', 'Hot update is deprecated, please download the full installer for the best experience', '熱更新已棄用,請下載完整安裝包以獲得最佳體驗', 'ホットアップデートは非推奨です。最高の体験のためにフルインストーラーをダウンロードしてください', '핫 업데이트는 더 이상 사용되지 않습니다. 최상의 경험을 위해 전체 설치 프로그램을 다운로드하세요'),
|
||||
downloadFullInstaller: _('下载完整安装包', 'Download Full Installer', '下載完整安裝包', 'フルインストーラーをダウンロード', '전체 설치 프로그램 다운로드'),
|
||||
upToDate: _('已是最新', 'Up to date', '', '最新です', '최신 상태', 'Đã cập nhật', 'Actualizado', 'Atualizado', 'Актуально', 'À jour', 'Aktuell'),
|
||||
checkUpdateFailed: _('暂无法检查更新', 'Unable to check for updates', '暫無法檢查更新', '更新を確認できません', '업데이트 확인 실패', 'Kiểm tra cập nhật thất bại', 'Error al verificar actualizaciones', 'Falha ao verificar atualizações', 'Ошибка проверки обновлений', 'Échec de la vérification des mises à jour', 'Update-Prüfung fehlgeschlagen'),
|
||||
qqGroup: _('QQ 交流群', 'QQ Group'),
|
||||
|
||||
@@ -74,14 +74,10 @@ async function loadHermesData(page) {
|
||||
api.checkPython().catch(() => null),
|
||||
])
|
||||
|
||||
let panelVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0'
|
||||
try {
|
||||
const { getVersion } = await import('@tauri-apps/api/app')
|
||||
panelVersion = await getVersion()
|
||||
} catch {}
|
||||
const panelVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0'
|
||||
|
||||
let panelUpdateHtml = `<span style="color:var(--text-tertiary)">${t('about.checkingUpdate')}</span>`
|
||||
checkHotUpdate(cards, panelVersion)
|
||||
checkNewVersion(cards, panelVersion)
|
||||
|
||||
const installed = !!hermesInfo?.installed
|
||||
const gwRunning = !!hermesInfo?.gatewayRunning
|
||||
@@ -130,17 +126,10 @@ async function loadData(page) {
|
||||
])
|
||||
|
||||
// 尝试从 Tauri API 获取 ClawPanel 自身版本号,失败则 fallback
|
||||
let panelVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0'
|
||||
try {
|
||||
const { getVersion } = await import('@tauri-apps/api/app')
|
||||
panelVersion = await getVersion()
|
||||
} catch {
|
||||
// 非 Tauri 环境或 API 不可用,使用构建时注入的版本号
|
||||
}
|
||||
const panelVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0'
|
||||
|
||||
// 异步检查前端热更新
|
||||
let panelUpdateHtml = `<span style="color:var(--text-tertiary)">${t('about.checkingUpdate')}</span>`
|
||||
checkHotUpdate(cards, panelVersion)
|
||||
checkNewVersion(cards, panelVersion)
|
||||
|
||||
const isInstalled = !!version.current
|
||||
const sourceLabel = version.source === 'official' ? t('about.official') : version.source === 'chinese' ? t('about.chinese') : t('about.unknownSource')
|
||||
@@ -480,32 +469,54 @@ async function doInstall(page, title, source, version) {
|
||||
}
|
||||
}
|
||||
|
||||
async function checkHotUpdate(cards, panelVersion) {
|
||||
async function checkNewVersion(cards, panelVersion) {
|
||||
const el = () => cards.querySelector('#panel-update-meta')
|
||||
const btnSm = 'padding:2px 8px;font-size:var(--font-size-xs)'
|
||||
|
||||
// 尝试获取 Tauri 二进制版本,检测「假更新」:
|
||||
// 前端通过热更新升级到 v0.13.0,但 Tauri 二进制仍是 v0.9.9
|
||||
let binaryVersion = panelVersion
|
||||
try {
|
||||
const info = await api.checkFrontendUpdate()
|
||||
const { getVersion } = await import('@tauri-apps/api/app')
|
||||
binaryVersion = await getVersion()
|
||||
} catch {}
|
||||
|
||||
// 前端版本 > 二进制版本 = 热更新导致版本不一致
|
||||
const isFakeUpdate = binaryVersion !== panelVersion && compareVersions(panelVersion, binaryVersion) > 0
|
||||
|
||||
try {
|
||||
const info = await api.checkPanelUpdate()
|
||||
const meta = el()
|
||||
if (!meta) return
|
||||
|
||||
if (info.hasUpdate || info.updateReady) {
|
||||
const ver = info.latestVersion || info.manifest?.version || ''
|
||||
const changelog = info.manifest?.changelog || ''
|
||||
const latest = info?.latest || ''
|
||||
// 用二进制版本(真实应用版本)做比较,避免假更新导致误判为「已是最新」
|
||||
const effectiveVersion = isFakeUpdate ? binaryVersion : panelVersion
|
||||
|
||||
if (isFakeUpdate) {
|
||||
meta.innerHTML = `
|
||||
<span style="color:var(--accent)">${t('about.newVersion')}: v${ver}</span>
|
||||
${changelog ? `<span style="color:var(--text-tertiary);font-size:var(--font-size-xs)">${changelog}</span>` : ''}
|
||||
<a class="btn btn-primary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromWebsite')}</a>
|
||||
<a class="btn btn-secondary btn-sm" href="https://github.com/qingchencloud/clawpanel/releases" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromGitHub')}</a>
|
||||
<span style="color:var(--warning)">⚠️ ${t('about.versionMismatch', { frontend: panelVersion, binary: binaryVersion })}</span>
|
||||
<span style="color:var(--text-tertiary);font-size:var(--font-size-xs)">${t('about.hotUpdateDeprecated')}</span>
|
||||
<a class="btn btn-primary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFullInstaller')}</a>
|
||||
<a class="btn btn-secondary btn-sm" href="${info.url || 'https://github.com/qingchencloud/clawpanel/releases'}" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromGitHub')}</a>
|
||||
`
|
||||
} else if (latest && latest !== effectiveVersion && compareVersions(latest, effectiveVersion) > 0) {
|
||||
meta.innerHTML = `
|
||||
<span style="color:var(--accent)">${t('about.newVersionAvailable', { version: latest })}</span>
|
||||
<a class="btn btn-primary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromWebsite')}</a>
|
||||
<a class="btn btn-secondary btn-sm" href="${info.url || 'https://github.com/qingchencloud/clawpanel/releases'}" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromGitHub')}</a>
|
||||
`
|
||||
} else if (!info.compatible) {
|
||||
meta.innerHTML = `<span style="color:var(--text-tertiary)">${t('about.needFullUpdate')}</span> <a class="btn btn-primary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromWebsite')}</a> <a class="btn btn-secondary btn-sm" href="https://github.com/qingchencloud/clawpanel/releases" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFromGitHub')}</a>`
|
||||
} else {
|
||||
meta.innerHTML = `<span style="color:var(--success)">${t('about.upToDate')}</span>`
|
||||
}
|
||||
} catch (err) {
|
||||
const meta = el()
|
||||
if (!meta) return
|
||||
meta.innerHTML = `<span style="color:var(--text-tertiary)">${t('about.checkUpdateFailed')}</span> <a class="btn btn-secondary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.goToWebsite')}</a>`
|
||||
if (isFakeUpdate) {
|
||||
meta.innerHTML = `<span style="color:var(--warning)">⚠️ ${t('about.versionMismatch', { frontend: panelVersion, binary: binaryVersion })}</span> <a class="btn btn-primary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.downloadFullInstaller')}</a>`
|
||||
} else {
|
||||
meta.innerHTML = `<span style="color:var(--text-tertiary)">${t('about.checkUpdateFailed')}</span> <a class="btn btn-secondary btn-sm" href="https://claw.qt.cool" target="_blank" rel="noopener" style="${btnSm}">${t('about.goToWebsite')}</a>`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user