From a4df800d662ced14ee1d20a615ba250c26a28345 Mon Sep 17 00:00:00 2001 From: sim Date: Wed, 24 Jun 2026 12:31:39 +0800 Subject: [PATCH] chore(release): publish 1.3.12 - add OpenCode CLI provider support for voice agent workflows - improve updater fallback/error visibility and compatibility - bump app, Tauri, and Cargo versions to 1.3.12 --- openless-all/app/package-lock.json | 4 +- openless-all/app/package.json | 2 +- openless-all/app/src-tauri/Cargo.lock | 2 +- openless-all/app/src-tauri/Cargo.toml | 2 +- .../src-tauri/src/coding_agent/opencode.rs | 2 +- .../src-tauri/src/coordinator/dictation.rs | 2 +- openless-all/app/src-tauri/tauri.conf.json | 2 +- .../app/src/components/AutoUpdate.tsx | 157 +++++++++--------- 8 files changed, 83 insertions(+), 90 deletions(-) diff --git a/openless-all/app/package-lock.json b/openless-all/app/package-lock.json index 0526cf14..0587968b 100644 --- a/openless-all/app/package-lock.json +++ b/openless-all/app/package-lock.json @@ -1,12 +1,12 @@ { "name": "openless-app", - "version": "1.3.11", + "version": "1.3.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openless-app", - "version": "1.3.11", + "version": "1.3.12", "dependencies": { "@formkit/auto-animate": "^0.9.0", "@tauri-apps/api": "^2.1.1", diff --git a/openless-all/app/package.json b/openless-all/app/package.json index 60d0cefb..20ff4203 100644 --- a/openless-all/app/package.json +++ b/openless-all/app/package.json @@ -1,7 +1,7 @@ { "name": "openless-app", "private": true, - "version": "1.3.11", + "version": "1.3.12", "type": "module", "scripts": { "dev": "vite", diff --git a/openless-all/app/src-tauri/Cargo.lock b/openless-all/app/src-tauri/Cargo.lock index a72a299f..b4755cd5 100644 --- a/openless-all/app/src-tauri/Cargo.lock +++ b/openless-all/app/src-tauri/Cargo.lock @@ -3883,7 +3883,7 @@ dependencies = [ [[package]] name = "openless" -version = "1.3.11" +version = "1.3.12" dependencies = [ "anyhow", "arboard", diff --git a/openless-all/app/src-tauri/Cargo.toml b/openless-all/app/src-tauri/Cargo.toml index ba7fa19b..e4d2d907 100644 --- a/openless-all/app/src-tauri/Cargo.toml +++ b/openless-all/app/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openless" -version = "1.3.11" +version = "1.3.12" description = "OpenLess — local voice input that types where your cursor is" authors = ["OpenLess"] edition = "2021" diff --git a/openless-all/app/src-tauri/src/coding_agent/opencode.rs b/openless-all/app/src-tauri/src/coding_agent/opencode.rs index e0b1819a..ec00a2de 100644 --- a/openless-all/app/src-tauri/src/coding_agent/opencode.rs +++ b/openless-all/app/src-tauri/src/coding_agent/opencode.rs @@ -16,7 +16,7 @@ //! [`CodingAgentEvent::Completed`],`cost_usd = None`(OpenCode CLI 不在 JSON 里给单次成本)。 use std::process::Stdio; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::time::Duration; diff --git a/openless-all/app/src-tauri/src/coordinator/dictation.rs b/openless-all/app/src-tauri/src/coordinator/dictation.rs index 7d312e67..187087fa 100644 --- a/openless-all/app/src-tauri/src/coordinator/dictation.rs +++ b/openless-all/app/src-tauri/src/coordinator/dictation.rs @@ -415,7 +415,7 @@ fn finalize_polished_text( polished: String, translation_active: bool, _raw_uses_llm: bool, - mode: PolishMode, + _mode: PolishMode, polish_error: &Option, chinese_script_preference: crate::types::ChineseScriptPreference, correction_rules: &[crate::types::CorrectionRule], diff --git a/openless-all/app/src-tauri/tauri.conf.json b/openless-all/app/src-tauri/tauri.conf.json index 42bb03d2..bfe375cc 100644 --- a/openless-all/app/src-tauri/tauri.conf.json +++ b/openless-all/app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "OpenLess", - "version": "1.3.11", + "version": "1.3.12", "identifier": "com.openless.app", "build": { "beforeDevCommand": "npm run dev", diff --git a/openless-all/app/src/components/AutoUpdate.tsx b/openless-all/app/src/components/AutoUpdate.tsx index 8b694f44..1c8842c9 100644 --- a/openless-all/app/src/components/AutoUpdate.tsx +++ b/openless-all/app/src/components/AutoUpdate.tsx @@ -1,10 +1,9 @@ -// 自动更新共用模块 — Settings 的"关于"section 和 AutoUpdateGate 共用同一套 -// 状态机 + 对话框 UI。各自调用 useAutoUpdate(),dialog 渲染条件相同。 +// 自动更新共用模块 — Settings 的"关于"section 和 footer 按钮共用同一套 +// 状态机 + 对话框 UI。两边各自调用 useAutoUpdate(),dialog 渲染条件相同。 // // 渠道感知:check 走 appCheckUpdateWithChannel()(Rust 按渠道拼 manifest URL)。 // 桌面:download/install 复用 plugin-updater 的 Update 类。 // Android:download/install 走 appDownloadAndInstallAndroidUpdate(minisign + 系统安装器)。 -// Android 后台 Gate:发现更新后 autoInstallAndroid 跳过确认,直接下载并打开系统安装器。 import { useEffect, useRef, useState } from 'react'; import type { DownloadEvent } from '@tauri-apps/plugin-updater'; @@ -71,8 +70,6 @@ type AndroidUpdatePayload = { export function useAutoUpdate(): UseAutoUpdate { const updateRef = useRef(null); const androidUpdateRef = useRef(null); - /** True only while this hook instance initiated an Android download/install. */ - const androidDownloadActiveRef = useRef(false); const [status, setStatus] = useState('idle'); const [version, setVersion] = useState(''); const [downloaded, setDownloaded] = useState(0); @@ -110,7 +107,6 @@ export function useAutoUpdate(): UseAutoUpdate { contentLength: number | null; phase: string; }>('android-update:progress', (event) => { - if (!androidDownloadActiveRef.current) return; setDownloaded(event.payload.downloaded); setContentLength(event.payload.contentLength); if (event.payload.phase === 'installing') { @@ -141,30 +137,87 @@ export function useAutoUpdate(): UseAutoUpdate { androidUpdateRef.current = { url, signature, version: metadata.version }; }; - const installAndroidUpdate = async () => { - const payload = androidUpdateRef.current; - if (!payload) return; + const checkForUpdates = async (channel?: UpdateChannel, options?: CheckUpdateOptions) => { + setStatus('checking'); + setVersion(''); + setErrorMessage(null); resetProgress(); - setStatus('downloading'); - androidDownloadActiveRef.current = true; + await closeUpdate(); try { - await appDownloadAndInstallAndroidUpdate(payload); - androidUpdateRef.current = null; - setStatus('downloaded'); + if (!isTauri) { + setStatus('none'); + return; + } + const metadata = await appCheckUpdateWithChannel( + UPDATE_CHECK_TIMEOUT_MS, + channel ?? null, + ); + if (!metadata) { + setStatus('none'); + return; + } + if (isAndroid()) { + storeAndroidMetadata(metadata); + setVersion(metadata.version); + if (options?.autoInstallAndroid) { + try { + // 复用 storeAndroidMetadata 的 rawJson 解析(提取 url/signature/version) + const raw = metadata.rawJson ?? {}; + const url = typeof raw.url === 'string' ? raw.url : ''; + const signature = typeof raw.signature === 'string' ? raw.signature : ''; + if (!url || !signature) { + console.warn('[auto-update] android manifest missing url/signature, falling back to manual update'); + setStatus('available'); + return; + } + await appDownloadAndInstallAndroidUpdate({ url, signature, version: metadata.version }); + setStatus('downloaded'); + } catch (error) { + console.warn('[auto-update] android auto-install failed', error); + setStatus('available'); + } + return; + } + setStatus('available'); + return; + } + const next = new Update({ + rid: metadata.rid, + currentVersion: metadata.currentVersion, + version: metadata.version, + date: metadata.date ?? undefined, + body: metadata.body ?? undefined, + rawJson: metadata.rawJson, + }); + updateRef.current = next; + setVersion(next.version); + setStatus('available'); } catch (error) { - console.error('[updater] failed to install android update', error); + console.error('[updater] failed to check update', error); const msg = error instanceof Error ? error.message : String(error); - void logClientError(`[updater] android install failed (v${payload.version}): ${msg}`); + void logClientError(`[updater] check failed: ${msg}`); setErrorMessage(msg); - setStatus('installError'); - } finally { - androidDownloadActiveRef.current = false; + setStatus('error'); } }; const installUpdate = async () => { if (isAndroid()) { - await installAndroidUpdate(); + const payload = androidUpdateRef.current; + if (!payload) return; + resetProgress(); + setStatus('downloading'); + try { + await appDownloadAndInstallAndroidUpdate(payload); + androidUpdateRef.current = null; + setStatus('downloaded'); + } catch (error) { + console.error('[updater] failed to install android update', error); + const msg = error instanceof Error ? error.message : String(error); + void logClientError(`[updater] android install failed (v${payload.version}): ${msg}`); + setErrorMessage(msg); + setStatus('installError'); + } return; } @@ -197,59 +250,6 @@ export function useAutoUpdate(): UseAutoUpdate { } }; - const checkForUpdates = async (channel?: UpdateChannel, options?: CheckUpdateOptions) => { - setStatus('checking'); - setVersion(''); - setErrorMessage(null); - resetProgress(); - await closeUpdate(); - try { - if (!isTauri) { - setStatus('none'); - return; - } - const metadata = await appCheckUpdateWithChannel( - UPDATE_CHECK_TIMEOUT_MS, - channel ?? null, - ); - if (!metadata) { - setStatus('none'); - return; - } - if (isAndroid()) { - storeAndroidMetadata(metadata); - setVersion(metadata.version); - if (options?.autoInstallAndroid) { - try { - await installAndroidUpdate(); - } catch (error) { - console.warn('[auto-update] android auto-install failed', error); - } - return; - } - setStatus('available'); - return; - } - const next = new Update({ - rid: metadata.rid, - currentVersion: metadata.currentVersion, - version: metadata.version, - date: metadata.date ?? undefined, - body: metadata.body ?? undefined, - rawJson: metadata.rawJson, - }); - updateRef.current = next; - setVersion(next.version); - setStatus('available'); - } catch (error) { - console.error('[updater] failed to check update', error); - const msg = error instanceof Error ? error.message : String(error); - void logClientError(`[updater] check failed: ${msg}`); - setErrorMessage(msg); - setStatus('error'); - } - }; - const dismissDialog = async () => { if (busy) return; await closeUpdate(); @@ -301,17 +301,10 @@ export function UpdateDialog({ const installing = status === 'installing'; const installError = status === 'installError'; const androidInstalled = isAndroid() && status === 'downloaded'; - const installLabel = isAndroid() - ? t('settings.about.updateDialog.androidInstall') - : t('settings.about.updateDialog.install'); return (
-
- {androidInstalled - ? t('settings.about.updateDialog.androidInstalled.title') - : t(`settings.about.updateDialog.${status}.title`)} -
+
{t(`settings.about.updateDialog.${status}.title`)}
{androidInstalled ? t('settings.about.updateDialog.androidInstalled.desc', { version, defaultValue: '系统安装器已打开,请按提示完成安装。安装后重新打开 OpenLess 即可使用 {{version}}。' }) @@ -335,7 +328,7 @@ export function UpdateDialog({ )}
{status === 'available' && {t('common.cancel')}} - {status === 'available' && {installLabel}} + {status === 'available' && {t('settings.about.updateDialog.install')}} {(downloading || installing) && {installing ? t('settings.about.updateDialog.installingLabel') : t('settings.about.updateDialog.downloadingLabel')}} {status === 'downloaded' && {t('settings.about.updateDialog.later')}} {status === 'downloaded' && !androidInstalled && {t('settings.about.updateDialog.restartNow')}}