From d098066899815fc92c5062928915497e20cd577b Mon Sep 17 00:00:00 2001 From: Yuri Karamian Date: Tue, 24 Feb 2026 22:15:32 +0100 Subject: [PATCH] v1.1.7 - Fix Untitled note rename, Ollama support, replace Sonnet 4.5 with Sonnet 4.6 --- package.json | 2 +- src-tauri/Cargo.lock | 212 ++++++++++++------------ src-tauri/Cargo.toml | 2 +- src-tauri/src/ai.rs | 73 +++++--- src-tauri/src/commands.rs | 29 +++- src-tauri/src/types.rs | 7 +- src-tauri/tauri.conf.json | 2 +- src/lib/api.ts | 3 +- src/lib/components/Editor.svelte | 6 +- src/lib/components/SettingsPanel.svelte | 112 ++++++++----- src/lib/types.ts | 1 + 11 files changed, 271 insertions(+), 178 deletions(-) diff --git a/package.json b/package.json index c992046..1400573 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "helixnotes", "private": true, "license": "AGPL-3.0-or-later", - "version": "1.1.6", + "version": "1.1.7", "type": "module", "scripts": { "dev": "vite dev", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2a968c5..6fd986e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -89,9 +89,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -174,7 +174,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.3", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] @@ -205,7 +205,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -216,7 +216,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -231,7 +231,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.1.3", + "rustix 1.1.4", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -251,7 +251,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -388,7 +388,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -414,9 +414,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6f81257d10a0f602a294ae4182251151ff97dbb504ef9afcdda4a64b24d9b4" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-unit" @@ -605,9 +605,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -784,7 +784,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -794,7 +794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -818,7 +818,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -829,14 +829,14 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -850,7 +850,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -863,7 +863,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -923,7 +923,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -946,7 +946,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1050,7 +1050,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1208,7 +1208,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1330,7 +1330,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1597,7 +1597,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1688,7 +1688,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1750,7 +1750,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "helixnotes" -version = "1.1.6" +version = "1.1.7" dependencies = [ "chrono", "dirs", @@ -2248,9 +2248,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "f4eacb0641a310445a4c513f2a5e23e19952e269c6a38887254d5f837a305506" dependencies = [ "once_cell", "wasm-bindgen", @@ -2393,7 +2393,7 @@ checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.11.0", "libc", - "redox_syscall 0.7.1", + "redox_syscall 0.7.2", ] [[package]] @@ -2404,9 +2404,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -2481,7 +2481,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2725,7 +2725,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3200,7 +3200,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3308,7 +3308,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -3349,7 +3349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3691,9 +3691,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6d94dd2f7cd932d4dc02cc8b2b50dfd38bd079a4e5d79198b99743d7fcf9a4b4" dependencies = [ "bitflags 2.11.0", ] @@ -3726,7 +3726,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rend" @@ -3976,22 +3976,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "log", "once_cell", @@ -4140,7 +4140,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4157,9 +4157,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "security-framework" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.11.0", "core-foundation", @@ -4170,9 +4170,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.16.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -4245,7 +4245,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4256,7 +4256,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4280,7 +4280,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4341,7 +4341,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4376,7 +4376,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4586,9 +4586,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4612,7 +4612,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4817,7 +4817,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4936,7 +4936,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.116", + "syn 2.0.117", "tauri-utils", "thiserror 2.0.18", "time", @@ -4954,7 +4954,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "tauri-codegen", "tauri-utils", ] @@ -5211,14 +5211,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.25.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", "getrandom 0.4.1", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -5259,7 +5259,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5270,7 +5270,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5356,7 +5356,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5551,7 +5551,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5835,9 +5835,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "05d7d0fce354c88b7982aec4400b3e7fcf723c32737cef571bd165f7613557ee" dependencies = [ "cfg-if", "once_cell", @@ -5848,9 +5848,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "ee85afca410ac4abba5b584b12e77ea225db6ee5471d0aebaae0861166f9378a" dependencies = [ "cfg-if", "futures-util", @@ -5862,9 +5862,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "55839b71ba921e4f75b674cb16f843f4b1f3b26ddfcb3454de1cf65cc021ec0f" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5872,22 +5872,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "caf2e969c2d60ff52e7e98b7392ff1588bffdd1ccd4769eba27222fd3d621571" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "0861f0dcdf46ea819407495634953cdcc8a8c7215ab799a7a7ce366be71c7b30" dependencies = [ "unicode-ident", ] @@ -5954,9 +5954,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "10053fbf9a374174094915bbce141e87a6bf32ecd9a002980db4b638405e8962" dependencies = [ "js-sys", "wasm-bindgen", @@ -6056,7 +6056,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6183,7 +6183,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6194,7 +6194,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6562,7 +6562,7 @@ dependencies = [ "heck 0.5.0", "indexmap 2.13.0", "prettyplease", - "syn 2.0.116", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -6578,7 +6578,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -6708,7 +6708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -6741,15 +6741,15 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] [[package]] name = "zbus" -version = "5.13.2" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfeff997a0aaa3eb20c4652baf788d2dfa6d2839a0ead0b3ff69ce2f9c4bdd1" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ "async-broadcast", "async-executor", @@ -6767,7 +6767,7 @@ dependencies = [ "hex", "libc", "ordered-stream", - "rustix 1.1.3", + "rustix 1.1.4", "serde", "serde_repr", "tracing", @@ -6782,14 +6782,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.13.2" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbd5a90dbe8feee5b13def448427ae314ccd26a49cac47905cafefb9ff846f1" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "zbus_names", "zvariant", "zvariant_utils", @@ -6823,7 +6823,7 @@ checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6843,7 +6843,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -6883,7 +6883,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6963,9 +6963,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.9.2" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b64ef4f40c7951337ddc7023dd03528a57a3ce3408ee9da5e948bd29b232c4" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" dependencies = [ "endi", "enumflags2", @@ -6977,14 +6977,14 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.9.2" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484d5d975eb7afb52cc6b929c13d3719a20ad650fea4120e6310de3fc55e415c" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "zvariant_utils", ] @@ -6997,6 +6997,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.116", + "syn 2.0.117", "winnow 0.7.14", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0414936..def8ee9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "helixnotes" -version = "1.1.6" +version = "1.1.7" description = "Local markdown note-taking app" authors = ["HelixNotes"] license = "AGPL-3.0-or-later" diff --git a/src-tauri/src/ai.rs b/src-tauri/src/ai.rs index a88b54f..6d34a0e 100644 --- a/src-tauri/src/ai.rs +++ b/src-tauri/src/ai.rs @@ -6,6 +6,7 @@ use crate::types::AiStreamEvent; const ANTHROPIC_API_URL: &str = "https://api.anthropic.com/v1/messages"; const OPENAI_API_URL: &str = "https://api.openai.com/v1/chat/completions"; +const OLLAMA_DEFAULT_URL: &str = "http://localhost:11434"; pub fn ai_request( app: AppHandle, @@ -15,6 +16,7 @@ pub fn ai_request( system_prompt: String, user_message: String, request_id: String, + base_url: Option, ) { std::thread::spawn(move || { let rt = tokio::runtime::Runtime::new().unwrap(); @@ -23,7 +25,22 @@ pub fn ai_request( "openai" => { stream_openai( &app, - &api_key, + OPENAI_API_URL, + Some(&api_key), + &model, + &system_prompt, + &user_message, + &request_id, + ) + .await + } + "ollama" => { + let url = base_url.as_deref().unwrap_or(OLLAMA_DEFAULT_URL); + let url = format!("{}/v1/chat/completions", url.trim_end_matches('/')); + stream_openai( + &app, + &url, + None, &model, &system_prompt, &user_message, @@ -188,7 +205,8 @@ async fn stream_anthropic( async fn stream_openai( app: &AppHandle, - api_key: &str, + url: &str, + api_key: Option<&str>, model: &str, system_prompt: &str, user_message: &str, @@ -224,10 +242,15 @@ async fn stream_openai( body["temperature"] = json!(0.7); } - let response = client - .post(OPENAI_API_URL) - .header("Authorization", format!("Bearer {}", api_key)) - .header("content-type", "application/json") + let mut req = client + .post(url) + .header("content-type", "application/json"); + + if let Some(key) = api_key { + req = req.header("Authorization", format!("Bearer {}", key)); + } + + let response = req .json(&body) .send() .await @@ -325,9 +348,19 @@ async fn stream_openai( Ok(()) } -pub async fn test_connection(provider: &str, api_key: &str, model: &str) -> Result { +pub async fn test_connection( + provider: &str, + api_key: &str, + model: &str, + base_url: Option<&str>, +) -> Result { match provider { - "openai" => test_openai(api_key, model).await, + "openai" => test_openai(OPENAI_API_URL, Some(api_key), model).await, + "ollama" => { + let url = base_url.unwrap_or(OLLAMA_DEFAULT_URL); + let url = format!("{}/v1/chat/completions", url.trim_end_matches('/')); + test_openai(&url, None, model).await + } _ => test_anthropic(api_key, model).await, } } @@ -365,19 +398,12 @@ async fn test_anthropic(api_key: &str, model: &str) -> Result { } } -async fn test_openai(api_key: &str, model: &str) -> Result { +async fn test_openai(url: &str, api_key: Option<&str>, model: &str) -> Result { let client = Client::new(); - let is_gpt5 = model.starts_with("gpt-5"); - let token_key = if is_gpt5 { - "max_completion_tokens" - } else { - "max_tokens" - }; - let body = json!({ "model": model, - token_key: 10, + "max_tokens": 10, "messages": [ { "role": "user", @@ -386,10 +412,15 @@ async fn test_openai(api_key: &str, model: &str) -> Result { ] }); - let response = client - .post(OPENAI_API_URL) - .header("Authorization", format!("Bearer {}", api_key)) - .header("content-type", "application/json") + let mut req = client + .post(url) + .header("content-type", "application/json"); + + if let Some(key) = api_key { + req = req.header("Authorization", format!("Bearer {}", key)); + } + + let response = req .json(&body) .send() .await diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 4a5a962..e2773f4 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1334,11 +1334,13 @@ pub fn set_ai_settings( api_key: Option, model: String, writing_style: Option, + base_url: Option, ) -> Result<(), String> { let mut config = state.config.lock().map_err(|e| e.to_string())?; let key = api_key.filter(|k| !k.is_empty()); match provider.as_deref() { Some("openai") => config.openai_api_key = key, + Some("ollama") => config.ollama_base_url = base_url.filter(|u| !u.trim().is_empty()), _ => config.ai_api_key = key, } config.ai_provider = provider; @@ -1350,27 +1352,36 @@ pub fn set_ai_settings( #[tauri::command] pub fn test_ai_connection(app: AppHandle) -> Result<(), String> { - let (provider, api_key, model) = { + let (provider, api_key, model, base_url) = { let state = app.state::(); let config = state.config.lock().map_err(|e| e.to_string())?; let provider = config .ai_provider .clone() .unwrap_or_else(|| "anthropic".to_string()); - let key = if provider == "openai" { + let key = if provider == "ollama" { + // Ollama doesn't require an API key + Some(String::new()) + } else if provider == "openai" { config.openai_api_key.clone() } else { config.ai_api_key.clone() } .ok_or("No API key configured")?; let model = config.ai_model.clone(); - (provider, key, model) + let base_url = config.ollama_base_url.clone(); + (provider, key, model, base_url) }; std::thread::spawn(move || { use tauri::Emitter; let rt = tokio::runtime::Runtime::new().unwrap(); - let result = rt.block_on(crate::ai::test_connection(&provider, &api_key, &model)); + let result = rt.block_on(crate::ai::test_connection( + &provider, + &api_key, + &model, + base_url.as_deref(), + )); match result { Ok(msg) => { let _ = app.emit( @@ -1397,14 +1408,16 @@ pub fn ai_ask( custom_prompt: Option, request_id: String, ) -> Result<(), String> { - let (provider, api_key, model, writing_style) = { + let (provider, api_key, model, writing_style, base_url) = { let state = app.state::(); let config = state.config.lock().map_err(|e| e.to_string())?; let provider = config .ai_provider .clone() .unwrap_or_else(|| "anthropic".to_string()); - let key = if provider == "openai" { + let key = if provider == "ollama" { + Some(String::new()) + } else if provider == "openai" { config.openai_api_key.clone() } else { config.ai_api_key.clone() @@ -1412,7 +1425,8 @@ pub fn ai_ask( .ok_or("No API key configured. Go to Settings > AI to set up your API key.")?; let model = config.ai_model.clone(); let style = config.ai_writing_style.clone(); - (provider, key, model, style) + let base_url = config.ollama_base_url.clone(); + (provider, key, model, style, base_url) }; let mut system_prompt = "You are a helpful writing assistant inside a note-taking app called HelixNotes. \ @@ -1458,6 +1472,7 @@ pub fn ai_ask( system_prompt, user_message, request_id, + base_url, ); Ok(()) } diff --git a/src-tauri/src/types.rs b/src-tauri/src/types.rs index 0b3e858..5db5fbd 100644 --- a/src-tauri/src/types.rs +++ b/src-tauri/src/types.rs @@ -93,6 +93,8 @@ pub struct AppConfig { pub ai_api_key: Option, #[serde(default)] pub openai_api_key: Option, + #[serde(default)] + pub ollama_base_url: Option, #[serde(default = "default_ai_model")] pub ai_model: String, #[serde(default)] @@ -132,7 +134,7 @@ fn default_max_versions() -> u32 { } fn default_ai_model() -> String { - "claude-sonnet-4-5-20250929".to_string() + "claude-sonnet-4-6".to_string() } impl Default for AppConfig { @@ -164,7 +166,8 @@ impl Default for AppConfig { ai_provider: None, ai_api_key: None, openai_api_key: None, - ai_model: "claude-sonnet-4-5-20250929".to_string(), + ollama_base_url: None, + ai_model: "claude-sonnet-4-6".to_string(), ai_writing_style: None, default_view_mode: false, show_tray_icon: false, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 96e02ef..87e589d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "HelixNotes", - "version": "1.1.6", + "version": "1.1.7", "identifier": "com.helixnotes.app", "build": { "frontendDist": "../build", diff --git a/src/lib/api.ts b/src/lib/api.ts index b0b91ef..0f242ae 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -314,8 +314,9 @@ export async function setAiSettings( apiKey: string | null, model: string, writingStyle: string | null, + baseUrl: string | null = null, ): Promise { - return invoke("set_ai_settings", { provider, apiKey, model, writingStyle }); + return invoke("set_ai_settings", { provider, apiKey, model, writingStyle, baseUrl }); } export async function testAiConnection(): Promise { diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index e2d2769..5e0ee14 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -2947,14 +2947,18 @@ if (!newTitle) return; const oldPath = $activeNotePath; $activeNote.meta.title = newTitle; + // Update stripped title so restoreTitleH1 uses the new title + if (titleWasStripped) strippedTitle = newTitle; $editorDirty = true; - autoSave(); + // Force save current editor content before renaming so disk is up-to-date + await forceSave(); // Rename file on disk if filename doesn't match the new title const filename = oldPath.split('/').pop() ?? ''; const stem = filename.replace(/\.md$/, ''); if (stem !== newTitle) { try { const newPath = await renameNote(oldPath, newTitle); + loadedPath = newPath; $activeNotePath = newPath; notes.update(list => list.map(n => n.path === oldPath diff --git a/src/lib/components/SettingsPanel.svelte b/src/lib/components/SettingsPanel.svelte index ac2442d..f66294d 100644 --- a/src/lib/components/SettingsPanel.svelte +++ b/src/lib/components/SettingsPanel.svelte @@ -204,18 +204,20 @@ let aiProvider = $state($appConfig?.ai_provider ?? null); let aiApiKey = $derived.by(() => { if (aiProvider === 'openai') return _openaiKey; + if (aiProvider === 'ollama') return ''; return _anthropicKey; }); let _anthropicKey = $state($appConfig?.ai_api_key ?? ''); let _openaiKey = $state($appConfig?.openai_api_key ?? ''); - let aiModel = $state($appConfig?.ai_model ?? 'claude-sonnet-4-5-20250929'); + let _ollamaBaseUrl = $state($appConfig?.ollama_base_url ?? 'http://localhost:11434'); + let aiModel = $state($appConfig?.ai_model ?? 'claude-sonnet-4-6'); let aiWritingStyle = $state($appConfig?.ai_writing_style ?? ''); let aiShowKey = $state(false); let aiTestLoading = $state(false); let aiTestMessage = $state<{ type: 'success' | 'error'; text: string } | null>(null); const anthropicModels = [ - { value: 'claude-sonnet-4-5-20250929', label: 'Claude Sonnet 4.5', desc: 'Balanced' }, + { value: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6', desc: 'Balanced' }, { value: 'claude-opus-4-6', label: 'Claude Opus 4.6', desc: 'Most capable' }, { value: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5', desc: 'Fast' }, ]; @@ -228,13 +230,15 @@ let aiModels = $derived(aiProvider === 'openai' ? openaiModels : anthropicModels); async function saveAiSettings() { - await setAiSettings(aiProvider, aiApiKey || null, aiModel, aiWritingStyle || null); + const baseUrl = aiProvider === 'ollama' ? (_ollamaBaseUrl || null) : null; + await setAiSettings(aiProvider, aiApiKey || null, aiModel, aiWritingStyle || null, baseUrl); if ($appConfig) { $appConfig = { ...$appConfig, ai_provider: aiProvider, ai_api_key: _anthropicKey || null, openai_api_key: _openaiKey || null, + ollama_base_url: _ollamaBaseUrl || null, ai_model: aiModel, ai_writing_style: aiWritingStyle || null, }; @@ -981,52 +985,86 @@

Provider

- + +
{#if aiProvider} -
-

API Key

-
+ {#if aiProvider === 'ollama'} +

Your data stays on your device. No text is sent to any external server.

+ {:else} +

Your selected text and note content will be sent to {aiProvider === 'openai' ? 'OpenAI' : 'Anthropic'} servers for processing.

+ {/if} + + {#if aiProvider === 'ollama'} +
+

Server URL

{ const v = (e.target as HTMLInputElement).value; if (aiProvider === 'openai') _openaiKey = v; else _anthropicKey = v; }} + placeholder="http://localhost:11434" + value={_ollamaBaseUrl} + oninput={(e) => { _ollamaBaseUrl = (e.target as HTMLInputElement).value; }} onblur={saveAiSettings} /> - +

Ollama server address. Install from ollama.com

- {#if aiProvider === 'openai'} -

Get your API key from platform.openai.com

- {:else} -

Get your API key from console.anthropic.com

- {/if} -
+ {:else} +
+

API Key

+
+ { const v = (e.target as HTMLInputElement).value; if (aiProvider === 'openai') _openaiKey = v; else _anthropicKey = v; }} + onblur={saveAiSettings} + /> + +
+ {#if aiProvider === 'openai'} +

Get your API key from platform.openai.com

+ {:else} +

Get your API key from console.anthropic.com

+ {/if} +
+ {/if}

Model

-
- {#each aiModels as m} - - {/each} -
+ {#if aiProvider === 'ollama'} + { aiModel = (e.target as HTMLInputElement).value; }} + onblur={saveAiSettings} + /> +

Enter the model name as shown by ollama list

+ {:else} +
+ {#each aiModels as m} + + {/each} +
+ {/if}
@@ -1044,7 +1082,7 @@

Connection

-