v1.1.7 - Fix Untitled note rename, Ollama support, replace Sonnet 4.5 with Sonnet 4.6

This commit is contained in:
Yuri Karamian
2026-02-24 22:15:32 +01:00
parent 9e2f347a4b
commit d098066899
11 changed files with 271 additions and 178 deletions
+1 -1
View File
@@ -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",
+106 -106
View File
@@ -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",
]
+1 -1
View File
@@ -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"
+52 -21
View File
@@ -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<String>,
) {
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<String, String> {
pub async fn test_connection(
provider: &str,
api_key: &str,
model: &str,
base_url: Option<&str>,
) -> Result<String, String> {
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<String, String> {
}
}
async fn test_openai(api_key: &str, model: &str) -> Result<String, String> {
async fn test_openai(url: &str, api_key: Option<&str>, model: &str) -> Result<String, String> {
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<String, String> {
]
});
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
+22 -7
View File
@@ -1334,11 +1334,13 @@ pub fn set_ai_settings(
api_key: Option<String>,
model: String,
writing_style: Option<String>,
base_url: Option<String>,
) -> 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::<AppState>();
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<String>,
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::<AppState>();
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(())
}
+5 -2
View File
@@ -93,6 +93,8 @@ pub struct AppConfig {
pub ai_api_key: Option<String>,
#[serde(default)]
pub openai_api_key: Option<String>,
#[serde(default)]
pub ollama_base_url: Option<String>,
#[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,
+1 -1
View File
@@ -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",
+2 -1
View File
@@ -314,8 +314,9 @@ export async function setAiSettings(
apiKey: string | null,
model: string,
writingStyle: string | null,
baseUrl: string | null = null,
): Promise<void> {
return invoke("set_ai_settings", { provider, apiKey, model, writingStyle });
return invoke("set_ai_settings", { provider, apiKey, model, writingStyle, baseUrl });
}
export async function testAiConnection(): Promise<void> {
+5 -1
View File
@@ -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
+75 -37
View File
@@ -204,18 +204,20 @@
let aiProvider = $state<string | null>($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 @@
<h3>Provider</h3>
<div class="setting-options">
<button class="option-btn" class:active={!aiProvider} onclick={() => { if (!aiProvider) return; aiProvider = null; aiTestMessage = null; saveAiSettings(); }}>Disabled</button>
<button class="option-btn" class:active={aiProvider === 'anthropic'} onclick={() => { if (aiProvider === 'anthropic') return; aiProvider = 'anthropic'; aiModel = 'claude-sonnet-4-5-20250929'; aiTestMessage = null; saveAiSettings(); }}>Anthropic</button>
<button class="option-btn" class:active={aiProvider === 'ollama'} onclick={() => { if (aiProvider === 'ollama') return; aiProvider = 'ollama'; aiModel = 'gemma3:4b'; aiTestMessage = null; saveAiSettings(); }}>Ollama</button>
<button class="option-btn" class:active={aiProvider === 'anthropic'} onclick={() => { if (aiProvider === 'anthropic') return; aiProvider = 'anthropic'; aiModel = 'claude-sonnet-4-6'; aiTestMessage = null; saveAiSettings(); }}>Anthropic</button>
<button class="option-btn" class:active={aiProvider === 'openai'} onclick={() => { if (aiProvider === 'openai') return; aiProvider = 'openai'; aiModel = 'gpt-5.2'; aiTestMessage = null; saveAiSettings(); }}>OpenAI</button>
</div>
</div>
{#if aiProvider}
<div class="settings-section">
<h3>API Key</h3>
<div class="ai-key-row">
{#if aiProvider === 'ollama'}
<p class="setting-hint" style="color: var(--text-success, #4ade80); margin-top: -4px; margin-bottom: 12px;">Your data stays on your device. No text is sent to any external server.</p>
{:else}
<p class="setting-hint" style="color: var(--text-warning, #f59e0b); margin-top: -4px; margin-bottom: 12px;">Your selected text and note content will be sent to {aiProvider === 'openai' ? 'OpenAI' : 'Anthropic'} servers for processing.</p>
{/if}
{#if aiProvider === 'ollama'}
<div class="settings-section">
<h3>Server URL</h3>
<input
type={aiShowKey ? 'text' : 'password'}
type="text"
class="ai-key-input"
placeholder={aiProvider === 'openai' ? 'sk-...' : 'sk-ant-...'}
value={aiApiKey}
oninput={(e) => { 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}
/>
<button class="ai-key-toggle" onclick={() => aiShowKey = !aiShowKey} title={aiShowKey ? 'Hide' : 'Show'}>
{#if aiShowKey}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
{:else}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
{/if}
</button>
<p class="setting-hint">Ollama server address. Install from <a href="https://ollama.com" target="_blank" class="ai-link">ollama.com</a></p>
</div>
{#if aiProvider === 'openai'}
<p class="setting-hint">Get your API key from <a href="https://platform.openai.com/api-keys" target="_blank" class="ai-link">platform.openai.com</a></p>
{:else}
<p class="setting-hint">Get your API key from <a href="https://console.anthropic.com/settings/keys" target="_blank" class="ai-link">console.anthropic.com</a></p>
{/if}
</div>
{:else}
<div class="settings-section">
<h3>API Key</h3>
<div class="ai-key-row">
<input
type={aiShowKey ? 'text' : 'password'}
class="ai-key-input"
placeholder={aiProvider === 'openai' ? 'sk-...' : 'sk-ant-...'}
value={aiApiKey}
oninput={(e) => { const v = (e.target as HTMLInputElement).value; if (aiProvider === 'openai') _openaiKey = v; else _anthropicKey = v; }}
onblur={saveAiSettings}
/>
<button class="ai-key-toggle" onclick={() => aiShowKey = !aiShowKey} title={aiShowKey ? 'Hide' : 'Show'}>
{#if aiShowKey}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
{:else}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
{/if}
</button>
</div>
{#if aiProvider === 'openai'}
<p class="setting-hint">Get your API key from <a href="https://platform.openai.com/api-keys" target="_blank" class="ai-link">platform.openai.com</a></p>
{:else}
<p class="setting-hint">Get your API key from <a href="https://console.anthropic.com/settings/keys" target="_blank" class="ai-link">console.anthropic.com</a></p>
{/if}
</div>
{/if}
<div class="settings-section">
<h3>Model</h3>
<div class="ai-model-options">
{#each aiModels as m}
<button
class="ai-model-btn"
class:active={aiModel === m.value}
onclick={() => { aiModel = m.value; saveAiSettings(); }}
>
<span class="ai-model-name">{m.label}</span>
<span class="ai-model-desc">{m.desc}</span>
</button>
{/each}
</div>
{#if aiProvider === 'ollama'}
<input
type="text"
class="ai-key-input"
placeholder="gemma3:4b"
value={aiModel}
oninput={(e) => { aiModel = (e.target as HTMLInputElement).value; }}
onblur={saveAiSettings}
/>
<p class="setting-hint">Enter the model name as shown by <code>ollama list</code></p>
{:else}
<div class="ai-model-options">
{#each aiModels as m}
<button
class="ai-model-btn"
class:active={aiModel === m.value}
onclick={() => { aiModel = m.value; saveAiSettings(); }}
>
<span class="ai-model-name">{m.label}</span>
<span class="ai-model-desc">{m.desc}</span>
</button>
{/each}
</div>
{/if}
</div>
<div class="settings-section">
@@ -1044,7 +1082,7 @@
<div class="settings-section">
<h3>Connection</h3>
<button class="import-btn" onclick={handleTestAi} disabled={aiTestLoading || !aiApiKey}>
<button class="import-btn" onclick={handleTestAi} disabled={aiTestLoading || (aiProvider !== 'ollama' && !aiApiKey)}>
{#if aiTestLoading}
<svg class="spinner-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10" opacity="0.25" /><path d="M12 2a10 10 0 019.95 9" /></svg>
Testing...
+1
View File
@@ -60,6 +60,7 @@ export interface AppConfig {
ai_provider: string | null;
ai_api_key: string | null;
openai_api_key: string | null;
ollama_base_url: string | null;
ai_model: string;
ai_writing_style: string | null;
default_view_mode: boolean;