diff --git a/README.md b/README.md index 20b0a69..9d0b7e2 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,19 @@ It is designed for practical daily work: IDEs, chats, notes, CRM fields, email, - Transcribe audio and video files from the Files tab or by dropping files onto the widget. - Record calls with separate microphone and system-audio tracks on macOS, Windows, and Linux. - Keep local history for voice recordings, file transcriptions, calls, and live translations. +- Chat with the configured text model to search and analyze Talkis records, summarize calls, find tasks, and translate text. - Run managed local STT through one native `transcribe.cpp` runtime for Whisper, GigaAM, Qwen ASR, NVIDIA Parakeet, plus local text summaries through a managed GGUF LLM runtime. - Build native bundles for macOS, Windows, and Linux. ## Latest Changes +### v0.4.4 + +- Promoted the existing model chat from development mode to the product navigation on macOS, Windows, and Linux. +- Added direct Chat access from the desktop tray and production-safe `?tab=chat` navigation. +- The chat can search local Talkis records with cited sources, summarize recent calls and transcripts, extract tasks, translate text, and use the configured Cloud, API, or local text model. +- Chat messages remain stored locally, and existing development chat history is preserved during the product upgrade. + ### v0.4.3 - Restored the standard compact hotkey field in Settings, matching the selected-text translator control, while keeping the large live keycap visualization exclusive to onboarding. diff --git a/README.ru.md b/README.ru.md index 6a2cdd3..5ecd058 100644 --- a/README.ru.md +++ b/README.ru.md @@ -37,11 +37,19 @@ Talkis сделан для повседневной работы: IDE, чаты, - Транскрибация аудио и видео из вкладки `Файлы` или через перетаскивание файла на виджет. - Запись созвонов на macOS, Windows и Linux с отдельными дорожками микрофона и системного аудио. - Локальная история голосовых записей, файловых транскрибаций, созвонов и синхронных переводов. +- Чат с настроенной текстовой моделью для поиска и анализа записей Talkis, саммари созвонов, поиска задач и перевода текста. - Единый управляемый локальный STT runtime `transcribe.cpp` для Whisper, GigaAM, Qwen ASR, NVIDIA Parakeet и локальные summary через управляемый GGUF LLM runtime. - Нативные сборки для macOS, Windows и Linux. ## Последние изменения +### v0.4.4 + +- Существующий чат с моделью переведён из режима разработки в продуктовую навигацию на macOS, Windows и Linux. +- В системный трей добавлен прямой переход в «Чат», а маршрут `?tab=chat` теперь доступен в production-сборке. +- Чат умеет искать локальные записи Talkis со ссылками на источники, делать саммари последних созвонов и транскриптов, находить задачи, переводить текст и работать через настроенную облачную, API- или локальную текстовую модель. +- Сообщения чата остаются на устройстве, а существующая история dev-чата сохраняется после продуктового обновления. + ### v0.4.3 - В настройках восстановлено стандартное компактное поле горячей клавиши по образцу переводчика выделенного текста, а крупная живая визуализация клавиш оставлена только в онбординге. diff --git a/docs/release/review-v0.4.4.md b/docs/release/review-v0.4.4.md new file mode 100644 index 0000000..64b1e56 --- /dev/null +++ b/docs/release/review-v0.4.4.md @@ -0,0 +1,75 @@ +# Release Review v0.4.4 + +## Release + +- Version: 0.4.4 +- Release branch: `release/v0.4.4` +- Target tag: `v0.4.4` +- Reviewer: Codex +- Date: 2026-07-31 + +## Scope + +- Key changes included in this release: + - Opens the existing model chat in production builds instead of gating it behind `import.meta.env.DEV`. + - Treats `chat` as a normal settings destination for URL and application-event navigation. + - Adds a Chat item to the desktop tray on all supported desktop platforms. + - Preserves the existing local IndexedDB namespace so development chat history survives the product upgrade. + - Rebuilds the tracked macOS `talkis-llm` sidecar for the synchronized `0.4.4` workspace version, matching the established release process. +- User-facing changes: + - Chat is available from the settings sidebar and system tray on macOS, Windows, and Linux. + - Users can search and cite Talkis records, summarize transcripts and calls, find tasks, translate text, and use the configured Cloud, API, or local text model. +- Risky areas: + - Production navigation and deep-link handling for the newly visible tab. + - Text-model availability and existing local-history search behavior in a wider product audience. + - Cross-platform tray routing to the settings window. + +## Checks run + +- Focused Chat tests for product navigation, scope enforcement, and local-history search: passed, `29/29`. +- `bunx tsc --noEmit`: passed. +- `cargo fmt --manifest-path src-tauri/Cargo.toml -- --check`: passed. +- `CARGO_INCREMENTAL=0 cargo check --manifest-path src-tauri/Cargo.toml`: passed. +- `CARGO_INCREMENTAL=0 cargo test --manifest-path src-tauri/Cargo.toml --lib tray::tests::maps_supported_tray_menu_actions`: passed, `1/1`. +- `bash scripts/check-version-sync.sh`: passed at `0.4.4`. +- `CARGO_INCREMENTAL=0 bun run check:release`: passed, including version sync, TypeScript/Rust checks, sidecar preparation, hotkey smoke `6/6`, and production frontend build. +- `CARGO_INCREMENTAL=0 bun run build:release:macos`: passed; produced the signed application bundle, DMG, updater archive, and updater signature. +- Built `Talkis.app` version: verified as `0.4.4` from `CFBundleShortVersionString`. +- `codesign --verify --deep --strict`: passed for the built and installed application bundles, including all four sidecars. +- `hdiutil verify`: passed for `Talkis_0.4.4_aarch64.dmg`. +- Release artifact SHA-256: + - `Talkis_0.4.4_aarch64.dmg`: `4f469f911859a850b62dc7f13f026764177894ab014ad4724b794b5478c10d7a` + - `Talkis.app.tar.gz`: `5ac3f74718e55f67258dfcc4c5af7ad255a2af54a8c1772b4060635640523a3c` + - `Talkis.app.tar.gz.sig`: `16e6fd78272c20e8d382a0a6e201362ec48288323cd3113b4281efb403133bdf` +- GitHub Release Preflight: pending. +- Native/GitHub Windows build: pending Release Preflight. +- Native/GitHub Linux build: pending Release Preflight. +- Additional manual checks: + - Installed `/Applications/Talkis.app` reports version `0.4.4`, passes strict code-signature verification, and launches successfully. + - The previous installed `0.4.3` bundle was moved to the macOS Trash as `Talkis-0.4.3-before-v0.4.4.app` before replacement. + - Static inspection of the compiled production asset confirms `chat` is in the normal settings tab set and `DevChatTab` is rendered without a development-mode gate. + - A direct visual click-through to Chat was not performed because the freshly signed local bundle opened the macOS permissions onboarding; system privacy settings were intentionally not changed during release verification. + +## Manual review + +- Hotkey flow: unchanged; mandatory release smoke test passed, `6/6`. +- Onboarding permissions: unchanged. +- Widget position and notice behavior: unchanged. +- Transcription quality and short-utterance handling: unchanged. +- README refreshed: yes, `README.md` and `README.ru.md` document the product Chat. + +## Findings + +- Blockers: + - Exact-commit three-platform preflight is still pending. +- Non-blocking issues: + - Bun 1.2.13 initially returned the known intermittent false `Cannot find module` error on the external-volume workspace; the immediate focused retry passed `2/2`. + - The first Rust test/check attempts stalled in the external-volume incremental directory after an interrupted compile. Repeating them with `CARGO_INCREMENTAL=0` passed; CI uses a fresh runner. +- Follow-ups after release: + - None identified yet. + +## Decision + +- Ready for `main` merge: no; exact-commit three-platform preflight is pending. +- Release preflight green on exact tag commit: no; pending. +- Ready for tag publish: no; pending. diff --git a/package.json b/package.json index 9922b66..b2c8beb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "talkis", "private": true, - "version": "0.4.3", + "version": "0.4.4", "license": "AGPL-3.0-or-later", "type": "module", "packageManager": "bun@1.2.13", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9af0171..6771f6d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5725,7 +5725,7 @@ dependencies = [ [[package]] name = "talkis" -version = "0.4.3" +version = "0.4.4" dependencies = [ "base64 0.22.1", "block2 0.6.2", @@ -5774,7 +5774,7 @@ dependencies = [ [[package]] name = "talkis-llm" -version = "0.4.3" +version = "0.4.4" dependencies = [ "llama-cpp-2", "serde_json", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e22f62a..0bf8e39 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "talkis" -version = "0.4.3" +version = "0.4.4" description = "Talkis - Voice to Text Desktop Widget" authors = ["trixter"] license = "AGPL-3.0-or-later" @@ -13,7 +13,7 @@ default-members = ["."] resolver = "2" [workspace.package] -version = "0.4.3" +version = "0.4.4" edition = "2021" license = "AGPL-3.0-or-later" diff --git a/src-tauri/binaries/talkis-llm-aarch64-apple-darwin b/src-tauri/binaries/talkis-llm-aarch64-apple-darwin index 9295c45..45bacc5 100755 Binary files a/src-tauri/binaries/talkis-llm-aarch64-apple-darwin and b/src-tauri/binaries/talkis-llm-aarch64-apple-darwin differ diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 5d70214..7a29828 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -11,6 +11,7 @@ const TRAY_ID: &str = "talkis-main-tray"; const TRAY_OPEN_ID: &str = "talkis-tray-open"; const TRAY_HISTORY_ID: &str = "talkis-tray-history"; const TRAY_FILE_ID: &str = "talkis-tray-file"; +const TRAY_CHAT_ID: &str = "talkis-tray-chat"; const TRAY_MODELS_ID: &str = "talkis-tray-models"; const TRAY_TRANSLATOR_ID: &str = "talkis-tray-translator"; const TRAY_PROMPTS_ID: &str = "talkis-tray-prompts"; @@ -36,6 +37,7 @@ enum TrayAction { Open, History, FileTranscription, + Chat, Models, Translator, Prompts, @@ -54,6 +56,7 @@ fn tray_action(menu_id: &str) -> Option { TRAY_OPEN_ID => Some(TrayAction::Open), TRAY_HISTORY_ID => Some(TrayAction::History), TRAY_FILE_ID => Some(TrayAction::FileTranscription), + TRAY_CHAT_ID => Some(TrayAction::Chat), TRAY_MODELS_ID => Some(TrayAction::Models), TRAY_TRANSLATOR_ID => Some(TrayAction::Translator), TRAY_PROMPTS_ID => Some(TrayAction::Prompts), @@ -116,6 +119,7 @@ pub fn setup(app: &App) -> tauri::Result<()> { let history_item = MenuItem::with_id(app, TRAY_HISTORY_ID, "История", true, None::<&str>)?; let file_item = MenuItem::with_id(app, TRAY_FILE_ID, "Транскрибация файла", true, None::<&str>)?; + let chat_item = MenuItem::with_id(app, TRAY_CHAT_ID, "Чат", true, None::<&str>)?; let models_item = MenuItem::with_id(app, TRAY_MODELS_ID, "Диктовка и модели", true, None::<&str>)?; let translator_item = @@ -177,6 +181,7 @@ pub fn setup(app: &App) -> tauri::Result<()> { &navigation_separator, &history_item, &file_item, + &chat_item, &models_item, &translator_item, &prompts_item, @@ -202,6 +207,7 @@ pub fn setup(app: &App) -> tauri::Result<()> { Some(TrayAction::Open) => open_settings(app), Some(TrayAction::History) => open_settings_tab(app, "main"), Some(TrayAction::FileTranscription) => open_settings_tab(app, "file"), + Some(TrayAction::Chat) => open_settings_tab(app, "chat"), Some(TrayAction::Models) => open_settings_tab(app, "model"), Some(TrayAction::Translator) => open_settings_tab(app, "interpreter"), Some(TrayAction::Prompts) => open_settings_tab(app, "style"), @@ -241,6 +247,7 @@ mod tests { tray_action(TRAY_FILE_ID), Some(TrayAction::FileTranscription) ); + assert_eq!(tray_action(TRAY_CHAT_ID), Some(TrayAction::Chat)); assert_eq!(tray_action(TRAY_MODELS_ID), Some(TrayAction::Models)); assert_eq!( tray_action(TRAY_TRANSLATOR_ID), diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4b33a3b..84c98ce 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "https://schema.tauri.app/config/2", "productName": "Talkis", "mainBinaryName": "Talkis", - "version": "0.4.3", + "version": "0.4.4", "identifier": "com.trixter.talkis", "build": { "beforeDevCommand": "bun scripts/run-vite.mjs --talkis-check-dev-port && bun run dev", diff --git a/src/lib/hotkeyEvents.ts b/src/lib/hotkeyEvents.ts index dfe685c..720bc48 100644 --- a/src/lib/hotkeyEvents.ts +++ b/src/lib/hotkeyEvents.ts @@ -54,7 +54,7 @@ export interface HandyHotkeyEventPayload { } export interface SettingsNavigatePayload { - tab: "main" | "file" | "interpreter" | "settings" | "model" | "style"; + tab: "main" | "file" | "interpreter" | "chat" | "settings" | "model" | "style"; resultId?: string | null; } diff --git a/src/windows/settings/SettingsApp.tsx b/src/windows/settings/SettingsApp.tsx index 0907849..d773205 100644 --- a/src/windows/settings/SettingsApp.tsx +++ b/src/windows/settings/SettingsApp.tsx @@ -46,6 +46,11 @@ import { checkAllPermissions } from "../../lib/permissions"; import { logError } from "../../lib/logger"; import { UserPanel } from "../../components/UserPanel"; import { watchThemePreference } from "../../lib/theme"; +import { + isSettingsTab, + resolveInitialSettingsTab, + type SettingsTab as Tab, +} from "./settingsNavigation"; import { checkForAppUpdateNow, installAvailableAppUpdate, @@ -54,34 +59,8 @@ import { } from "../../lib/updater"; import { useI18n, type MsgKey } from "../../lib/i18n"; -type Tab = - "main" | "file" | "interpreter" | "chat" | "settings" | "model" | "style"; - -const SHOW_INTERPRETER_TAB = true; -const SHOW_DEV_CHAT_TAB = import.meta.env.DEV; - -function isVisibleTab(tab: Tab): boolean { - if (tab === "interpreter") return SHOW_INTERPRETER_TAB; - if (tab === "chat") return SHOW_DEV_CHAT_TAB; - return true; -} - function resolveInitialTab(): Tab { - const requestedTab = new URLSearchParams(window.location.search).get("tab"); - - if ( - requestedTab === "file" || - requestedTab === "chat" || - requestedTab === "settings" || - requestedTab === "model" || - requestedTab === "style" - ) { - return isVisibleTab(requestedTab) ? requestedTab : "main"; - } - - if (requestedTab === "interpreter") return "interpreter"; - - return "main"; + return resolveInitialSettingsTab(window.location.search); } const TABS: { id: Tab; labelKey: MsgKey; icon: Icon; note: string }[] = [ @@ -101,7 +80,7 @@ const TABS: { id: Tab; labelKey: MsgKey; icon: Icon; note: string }[] = [ id: "chat", labelKey: "settingsApp.tab.chat", icon: IconMessage, - note: "Dev chat", + note: "Чат с записями и текстом", }, { id: "model", @@ -143,8 +122,10 @@ function TabButton({ return (