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 | 137 +++++++++--------- 8 files changed, 73 insertions(+), 80 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,62 +137,6 @@ export function useAutoUpdate(): UseAutoUpdate { androidUpdateRef.current = { url, signature, version: metadata.version }; }; - const installAndroidUpdate = async () => { - const payload = androidUpdateRef.current; - if (!payload) return; - resetProgress(); - setStatus('downloading'); - androidDownloadActiveRef.current = true; - 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'); - } finally { - androidDownloadActiveRef.current = false; - } - }; - - const installUpdate = async () => { - if (isAndroid()) { - await installAndroidUpdate(); - return; - } - - const update = updateRef.current; - if (!update) return; - resetProgress(); - setStatus('downloading'); - try { - await update.download((event: DownloadEvent) => { - if (event.event === 'Started') { - resetProgress(); - setContentLength(event.data.contentLength ?? null); - } else if (event.event === 'Progress') { - setDownloaded(value => value + event.data.chunkLength); - } else if (event.event === 'Finished') { - setStatus('installing'); - } - }); - setStatus('installing'); - await update.install(); - await closeUpdate(); - setStatus('downloaded'); - } catch (error) { - console.error('[updater] failed to install update', error); - const msg = error instanceof Error ? error.message : String(error); - void logClientError(`[updater] install failed (v${update.version}): ${msg}`); - setErrorMessage(msg); - await closeUpdate(); - setStatus('installError'); - } - }; - const checkForUpdates = async (channel?: UpdateChannel, options?: CheckUpdateOptions) => { setStatus('checking'); setVersion(''); @@ -221,9 +161,20 @@ export function useAutoUpdate(): UseAutoUpdate { setVersion(metadata.version); if (options?.autoInstallAndroid) { try { - await installAndroidUpdate(); + // 复用 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; } @@ -250,6 +201,55 @@ export function useAutoUpdate(): UseAutoUpdate { } }; + const installUpdate = async () => { + if (isAndroid()) { + 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; + } + + const update = updateRef.current; + if (!update) return; + resetProgress(); + setStatus('downloading'); + try { + await update.download((event: DownloadEvent) => { + if (event.event === 'Started') { + resetProgress(); + setContentLength(event.data.contentLength ?? null); + } else if (event.event === 'Progress') { + setDownloaded(value => value + event.data.chunkLength); + } else if (event.event === 'Finished') { + setStatus('installing'); + } + }); + setStatus('installing'); + await update.install(); + await closeUpdate(); + setStatus('downloaded'); + } catch (error) { + console.error('[updater] failed to install update', error); + const msg = error instanceof Error ? error.message : String(error); + void logClientError(`[updater] install failed (v${update.version}): ${msg}`); + setErrorMessage(msg); + await closeUpdate(); + setStatus('installError'); + } + }; + 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')}}