diff --git a/extensions/llamacpp-extension/src/backend.ts b/extensions/llamacpp-extension/src/backend.ts index 9340aa4c0..c0fc7093d 100644 --- a/extensions/llamacpp-extension/src/backend.ts +++ b/extensions/llamacpp-extension/src/backend.ts @@ -74,7 +74,10 @@ async function fetchRemoteSupportedBackends( if (!name.startsWith(prefix)) continue - const backend = name.replace(prefix, '').replace('.tar.gz', '') + const backend = name + .replace(prefix, '') + .replace('.tar.gz', '') + .replace('.zip', '') if (supportedBackends.includes(backend)) { remote.push({ version, backend }) diff --git a/extensions/llamacpp-extension/src/index.ts b/extensions/llamacpp-extension/src/index.ts index 7229552a2..77b0aafcd 100644 --- a/extensions/llamacpp-extension/src/index.ts +++ b/extensions/llamacpp-extension/src/index.ts @@ -1081,11 +1081,11 @@ export default class llamacpp_extension extends AIEngine { */ async installBackend(path: string): Promise { const platformName = IS_WINDOWS ? 'win' : 'linux' - const re = /^llama-(b\d+)-bin-(.+?)\.tar\.gz$/ + const re = /^llama-(b\d+)-bin-(.+?)\.(?:tar\.gz|zip)$/ const archiveName = await basename(path) logger.info(`Installing backend from path: ${path}`) - if (!(await fs.existsSync(path)) || !path.endsWith('tar.gz')) { + if (!(await fs.existsSync(path)) || (!path.endsWith('tar.gz') && !path.endsWith('zip'))) { logger.error(`Invalid path or file ${path}`) throw new Error(`Invalid path or file ${path}`) } diff --git a/extensions/yarn.lock b/extensions/yarn.lock index c8fd66b30..0ca7755a3 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -517,41 +517,41 @@ __metadata: "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fcb200&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=63c6e9&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/603e79794614f861a9cf5693a4bbc480a62242309a6cb94a97c81e31518032c7462b2edad93a4380a18110f817ab15d85dc91a7924fd6e103a3462f6915ee368 + checksum: 10c0/417ea9bd3e5b53264596d2ee816c3e24299f8b721f6ea951d078342555da457ebca4d5b1e116bf187ac77ec0a9e3341211d464f4ffdbd2a3915139523688d41d languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fcb200&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=63c6e9&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/603e79794614f861a9cf5693a4bbc480a62242309a6cb94a97c81e31518032c7462b2edad93a4380a18110f817ab15d85dc91a7924fd6e103a3462f6915ee368 + checksum: 10c0/417ea9bd3e5b53264596d2ee816c3e24299f8b721f6ea951d078342555da457ebca4d5b1e116bf187ac77ec0a9e3341211d464f4ffdbd2a3915139523688d41d languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fcb200&locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=63c6e9&locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/603e79794614f861a9cf5693a4bbc480a62242309a6cb94a97c81e31518032c7462b2edad93a4380a18110f817ab15d85dc91a7924fd6e103a3462f6915ee368 + checksum: 10c0/417ea9bd3e5b53264596d2ee816c3e24299f8b721f6ea951d078342555da457ebca4d5b1e116bf187ac77ec0a9e3341211d464f4ffdbd2a3915139523688d41d languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=fcb200&locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=63c6e9&locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/603e79794614f861a9cf5693a4bbc480a62242309a6cb94a97c81e31518032c7462b2edad93a4380a18110f817ab15d85dc91a7924fd6e103a3462f6915ee368 + checksum: 10c0/417ea9bd3e5b53264596d2ee816c3e24299f8b721f6ea951d078342555da457ebca4d5b1e116bf187ac77ec0a9e3341211d464f4ffdbd2a3915139523688d41d languageName: node linkType: hard diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1e0d86600..85a90422a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -45,6 +45,7 @@ dependencies = [ "url", "uuid", "windows-sys 0.60.2", + "zip 0.6.6", ] [[package]] @@ -62,6 +63,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -358,6 +370,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bitflags" version = "1.3.2" @@ -508,6 +526,26 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "cairo-rs" version = "0.18.5" @@ -581,6 +619,8 @@ version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -638,6 +678,16 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "combine" version = "4.6.7" @@ -677,6 +727,12 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.4.0" @@ -2259,6 +2315,15 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "io-uring" version = "0.7.9" @@ -2373,6 +2438,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -3230,6 +3305,17 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" @@ -3242,6 +3328,18 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4521,6 +4619,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -5362,7 +5471,7 @@ dependencies = [ "tokio", "url", "windows-sys 0.60.2", - "zip", + "zip 4.3.0", ] [[package]] @@ -7199,6 +7308,26 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + [[package]] name = "zip" version = "4.3.0" @@ -7211,6 +7340,35 @@ dependencies = [ "memchr", ] +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zvariant" version = "5.6.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1152623be..51e84f880 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -59,6 +59,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_yaml = "0.9.34" tar = "0.4" +zip = "0.6" tauri-plugin-deep-link = { version = "2.3.4" } tauri-plugin-dialog = "2.2.1" tauri-plugin-hardware = { path = "./plugins/tauri-plugin-hardware" } diff --git a/src-tauri/src/core/filesystem/commands.rs b/src-tauri/src/core/filesystem/commands.rs index bfc29b415..7cf7803c6 100644 --- a/src-tauri/src/core/filesystem/commands.rs +++ b/src-tauri/src/core/filesystem/commands.rs @@ -200,8 +200,35 @@ pub fn decompress(app: tauri::AppHandle, path: &str, output_dir: &str) -> Result let tar = flate2::read::GzDecoder::new(file); let mut archive = tar::Archive::new(tar); archive.unpack(&output_dir_buf).map_err(|e| e.to_string())?; + } else if path.ends_with(".zip") { + let mut zip = zip::ZipArchive::new(file).map_err(|e| e.to_string())?; + for i in 0..zip.len() { + let mut entry = zip.by_index(i).map_err(|e| e.to_string())?; + let outpath = output_dir_buf.join( + entry + .enclosed_name() + .ok_or_else(|| "Invalid zip entry path".to_string())?, + ); + + if entry.name().ends_with('/') { + std::fs::create_dir_all(&outpath).map_err(|e| e.to_string())?; + } else { + if let Some(parent) = outpath.parent() { + std::fs::create_dir_all(parent).map_err(|e| e.to_string())?; + } + let mut outfile = std::fs::File::create(&outpath).map_err(|e| e.to_string())?; + std::io::copy(&mut entry, &mut outfile).map_err(|e| e.to_string())?; + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + if let Some(mode) = entry.unix_mode() { + let _ = std::fs::set_permissions(&outpath, std::fs::Permissions::from_mode(mode)); + } + } + } + } } else { - return Err("Unsupported file format. Only .tar.gz is supported.".to_string()); + return Err("Unsupported file format. Only .tar.gz and .zip are supported.".to_string()); } Ok(()) diff --git a/web-app/src/routes/settings/providers/$providerName.tsx b/web-app/src/routes/settings/providers/$providerName.tsx index efba6233c..18341193c 100644 --- a/web-app/src/routes/settings/providers/$providerName.tsx +++ b/web-app/src/routes/settings/providers/$providerName.tsx @@ -375,14 +375,14 @@ function ProviderDetail() { setIsInstallingBackend(true) try { - // Open file dialog with filter for .tar.gz files + // Open file dialog with filter for .tar.gz and .zip files const selectedFile = await serviceHub.dialog().open({ multiple: false, directory: false, filters: [ { name: 'Backend Archives', - extensions: ['tar.gz'], + extensions: ['tar.gz', 'zip'], }, ], }) diff --git a/yarn.lock b/yarn.lock index 71da89b17..1fd0b8545 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3532,8 +3532,8 @@ __metadata: "@tanstack/react-router-devtools": "npm:^1.121.34" "@tanstack/react-virtual": "npm:^3.13.12" "@tanstack/router-plugin": "npm:^1.116.1" - "@tauri-apps/api": "npm:^2.5.0" - "@tauri-apps/plugin-deep-link": "npm:~2" + "@tauri-apps/api": "npm:^2.8.0" + "@tauri-apps/plugin-deep-link": "npm:2.4.3" "@tauri-apps/plugin-dialog": "npm:^2.2.1" "@tauri-apps/plugin-http": "npm:^2.2.1" "@tauri-apps/plugin-opener": "npm:^2.2.7" @@ -3600,7 +3600,7 @@ __metadata: sonner: "npm:^2.0.3" tailwind-merge: "npm:^3.3.1" tailwindcss: "npm:^4.1.4" - token.js: "npm:token.js-fork@0.7.23" + token.js: "npm:token.js-fork@0.7.27" tw-animate-css: "npm:^1.2.7" typescript: "npm:~5.8.3" typescript-eslint: "npm:^8.26.1" @@ -7374,7 +7374,7 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/api@npm:^2.0.0, @tauri-apps/api@npm:^2.5.0": +"@tauri-apps/api@npm:^2.0.0": version: 2.5.0 resolution: "@tauri-apps/api@npm:2.5.0" checksum: 10c0/8eeb28049d48f5f89a5419cdf313bb159305204b193a5f27ebddbe0704ff43037c8b2e78518de831d7393e00178f0c0ac66cef1a57b99c632de71eca29f562c0 @@ -7388,6 +7388,13 @@ __metadata: languageName: node linkType: hard +"@tauri-apps/api@npm:^2.8.0": + version: 2.8.0 + resolution: "@tauri-apps/api@npm:2.8.0" + checksum: 10c0/fb111e4d7572372997b440ebe6879543fa8c4765151878e3fddfbfe809b18da29eed142ce83061d14a9ca6d896b3266dc8a4927c642d71cdc0b4277dc7e3aabf + languageName: node + linkType: hard + "@tauri-apps/cli-darwin-arm64@npm:2.8.4": version: 2.8.4 resolution: "@tauri-apps/cli-darwin-arm64@npm:2.8.4" @@ -7509,12 +7516,12 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/plugin-deep-link@npm:~2": - version: 2.3.0 - resolution: "@tauri-apps/plugin-deep-link@npm:2.3.0" +"@tauri-apps/plugin-deep-link@npm:2.4.3": + version: 2.4.3 + resolution: "@tauri-apps/plugin-deep-link@npm:2.4.3" dependencies: - "@tauri-apps/api": "npm:^2.0.0" - checksum: 10c0/76a8f0d4d89b243f4d1d663f0677c86df1bb5a508e4bca4700ca71e347e3b38cbf2217fd51c71b4051cde3481a3a2575dd957aec84bf5d95551edab3aa8c0e72 + "@tauri-apps/api": "npm:^2.8.0" + checksum: 10c0/948959e217241345edd3d866aa12ccfe97c72d96ab2844c1df156ead89a96b6a32106944a77f114e6027547c79556cd95f14c2d303a70b307222cce350c67988 languageName: node linkType: hard @@ -19617,9 +19624,9 @@ __metadata: languageName: node linkType: hard -"token.js@npm:token.js-fork@0.7.23": - version: 0.7.23 - resolution: "token.js-fork@npm:0.7.23" +"token.js@npm:token.js-fork@0.7.27": + version: 0.7.27 + resolution: "token.js-fork@npm:0.7.27" dependencies: "@anthropic-ai/sdk": "npm:0.24.3" "@aws-sdk/client-bedrock-runtime": "npm:3.609.0" @@ -19630,7 +19637,7 @@ __metadata: mime-types: "npm:^2.1.35" nanoid: "npm:^5.0.7" openai: "npm:4.91.1" - checksum: 10c0/73653dbdd2217f16de7eb294a2ef90ac985367f2ca421a2952a52c24de57e0f98db3ef668d8f36c361d6546513f85a480d48bfa916f2c5d65ce1b9033d526027 + checksum: 10c0/ec4e8e441b6747db29eed0d21e364eaf8d4636e3d8376bdd63d836499970de15357e8c0b2ef1e470027e7a2c8bc4924138a86f6d207469b6f0b6fb0f24f6d035 languageName: node linkType: hard