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
This commit is contained in:
1 parent
e1c1be2942
commit
a4df800d66
8 files changed
+83
-90
No files matched your search
Generated
+2
-2
@@ -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",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "openless-app",
|
||||
"private": true,
|
||||
"version": "1.3.11",
|
||||
"version": "1.3.12",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Generated
+1
-1
@@ -3883,7 +3883,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openless"
|
||||
version = "1.3.11"
|
||||
version = "1.3.12"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arboard",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ fn finalize_polished_text(
|
||||
polished: String,
|
||||
translation_active: bool,
|
||||
_raw_uses_llm: bool,
|
||||
mode: PolishMode,
|
||||
_mode: PolishMode,
|
||||
polish_error: &Option<String>,
|
||||
chinese_script_preference: crate::types::ChineseScriptPreference,
|
||||
correction_rules: &[crate::types::CorrectionRule],
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<Update | null>(null);
|
||||
const androidUpdateRef = useRef<AndroidUpdatePayload | null>(null);
|
||||
/** True only while this hook instance initiated an Android download/install. */
|
||||
const androidDownloadActiveRef = useRef(false);
|
||||
const [status, setStatus] = useState<UpdateStatus>('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 (
|
||||
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.18)', display: 'grid', placeItems: 'center', zIndex: 40 }}>
|
||||
<div style={{ width: 360, borderRadius: 16, background: 'var(--ol-surface)', border: '0.5px solid var(--ol-line-strong)', boxShadow: '0 18px 42px rgba(0,0,0,0.18)', padding: 18 }}>
|
||||
<div style={{ fontSize: 15, fontWeight: 650, marginBottom: 8 }}>
|
||||
{androidInstalled
|
||||
? t('settings.about.updateDialog.androidInstalled.title')
|
||||
: t(`settings.about.updateDialog.${status}.title`)}
|
||||
</div>
|
||||
<div style={{ fontSize: 15, fontWeight: 650, marginBottom: 8 }}>{t(`settings.about.updateDialog.${status}.title`)}</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--ol-ink-3)', lineHeight: 1.6, marginBottom: 14, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
|
||||
{androidInstalled
|
||||
? t('settings.about.updateDialog.androidInstalled.desc', { version, defaultValue: '系统安装器已打开,请按提示完成安装。安装后重新打开 OpenLess 即可使用 {{version}}。' })
|
||||
@@ -335,7 +328,7 @@ export function UpdateDialog({
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
|
||||
{status === 'available' && <Btn size="sm" onClick={onClose}>{t('common.cancel')}</Btn>}
|
||||
{status === 'available' && <Btn variant="blue" size="sm" onClick={onInstall}>{installLabel}</Btn>}
|
||||
{status === 'available' && <Btn variant="blue" size="sm" onClick={onInstall}>{t('settings.about.updateDialog.install')}</Btn>}
|
||||
{(downloading || installing) && <Btn size="sm" disabled>{installing ? t('settings.about.updateDialog.installingLabel') : t('settings.about.updateDialog.downloadingLabel')}</Btn>}
|
||||
{status === 'downloaded' && <Btn size="sm" onClick={onClose}>{t('settings.about.updateDialog.later')}</Btn>}
|
||||
{status === 'downloaded' && !androidInstalled && <Btn variant="blue" size="sm" onClick={restartApp}>{t('settings.about.updateDialog.restartNow')}</Btn>}
|
||||
|
||||
Reference in new issue
Block a user