Delete src-tauri directory
Signed-off-by: Web4 <137041369+QUBUHUB@users.noreply.github.com>
3
src-tauri/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
4811
src-tauri/Cargo.lock
generated
@ -1,49 +0,0 @@
|
||||
[package]
|
||||
name = "nextchat"
|
||||
version = "0.1.0"
|
||||
description = "A cross platform app for LLM ChatBot."
|
||||
authors = ["Yidadaa"]
|
||||
license = "mit"
|
||||
repository = ""
|
||||
default-run = "nextchat"
|
||||
edition = "2021"
|
||||
rust-version = "1.60"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.5.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.5.4", features = [ "http-all",
|
||||
"notification-all",
|
||||
"fs-all",
|
||||
"clipboard-all",
|
||||
"dialog-all",
|
||||
"shell-open",
|
||||
"updater",
|
||||
"window-close",
|
||||
"window-hide",
|
||||
"window-maximize",
|
||||
"window-minimize",
|
||||
"window-set-icon",
|
||||
"window-set-ignore-cursor-events",
|
||||
"window-set-resizable",
|
||||
"window-show",
|
||||
"window-start-dragging",
|
||||
"window-unmaximize",
|
||||
"window-unminimize",
|
||||
] }
|
||||
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||
percent-encoding = "2.3.1"
|
||||
reqwest = "0.11.18"
|
||||
futures-util = "0.3.30"
|
||||
bytes = "1.7.2"
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
||||
# DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 65 KiB |
@ -1,12 +0,0 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod stream;
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![stream::stream_fetch])
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
//
|
||||
//
|
||||
|
||||
use std::time::Duration;
|
||||
use std::error::Error;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::collections::HashMap;
|
||||
use futures_util::{StreamExt};
|
||||
use reqwest::Client;
|
||||
use reqwest::header::{HeaderName, HeaderMap};
|
||||
|
||||
static REQUEST_COUNTER: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct StreamResponse {
|
||||
request_id: u32,
|
||||
status: u16,
|
||||
status_text: String,
|
||||
headers: HashMap<String, String>
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
pub struct EndPayload {
|
||||
request_id: u32,
|
||||
status: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
pub struct ChunkPayload {
|
||||
request_id: u32,
|
||||
chunk: bytes::Bytes,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn stream_fetch(
|
||||
window: tauri::Window,
|
||||
method: String,
|
||||
url: String,
|
||||
headers: HashMap<String, String>,
|
||||
body: Vec<u8>,
|
||||
) -> Result<StreamResponse, String> {
|
||||
|
||||
let event_name = "stream-response";
|
||||
let request_id = REQUEST_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
let mut _headers = HeaderMap::new();
|
||||
for (key, value) in &headers {
|
||||
_headers.insert(key.parse::<HeaderName>().unwrap(), value.parse().unwrap());
|
||||
}
|
||||
|
||||
// println!("method: {:?}", method);
|
||||
// println!("url: {:?}", url);
|
||||
// println!("headers: {:?}", headers);
|
||||
// println!("headers: {:?}", _headers);
|
||||
|
||||
let method = method.parse::<reqwest::Method>().map_err(|err| format!("failed to parse method: {}", err))?;
|
||||
let client = Client::builder()
|
||||
.default_headers(_headers)
|
||||
.redirect(reqwest::redirect::Policy::limited(3))
|
||||
.connect_timeout(Duration::new(3, 0))
|
||||
.build()
|
||||
.map_err(|err| format!("failed to generate client: {}", err))?;
|
||||
|
||||
let mut request = client.request(
|
||||
method.clone(),
|
||||
url.parse::<reqwest::Url>().map_err(|err| format!("failed to parse url: {}", err))?
|
||||
);
|
||||
|
||||
if method == reqwest::Method::POST || method == reqwest::Method::PUT || method == reqwest::Method::PATCH {
|
||||
let body = bytes::Bytes::from(body);
|
||||
// println!("body: {:?}", body);
|
||||
request = request.body(body);
|
||||
}
|
||||
|
||||
// println!("client: {:?}", client);
|
||||
// println!("request: {:?}", request);
|
||||
|
||||
let response_future = request.send();
|
||||
|
||||
let res = response_future.await;
|
||||
let response = match res {
|
||||
Ok(res) => {
|
||||
// get response and emit to client
|
||||
let mut headers = HashMap::new();
|
||||
for (name, value) in res.headers() {
|
||||
headers.insert(
|
||||
name.as_str().to_string(),
|
||||
std::str::from_utf8(value.as_bytes()).unwrap().to_string()
|
||||
);
|
||||
}
|
||||
let status = res.status().as_u16();
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let mut stream = res.bytes_stream();
|
||||
|
||||
while let Some(chunk) = stream.next().await {
|
||||
match chunk {
|
||||
Ok(bytes) => {
|
||||
// println!("chunk: {:?}", bytes);
|
||||
if let Err(e) = window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }) {
|
||||
println!("Failed to emit chunk payload: {:?}", e);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error chunk: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Err(e) = window.emit(event_name, EndPayload{ request_id, status: 0 }) {
|
||||
println!("Failed to emit end payload: {:?}", e);
|
||||
}
|
||||
});
|
||||
|
||||
StreamResponse {
|
||||
request_id,
|
||||
status,
|
||||
status_text: "OK".to_string(),
|
||||
headers,
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let error: String = err.source()
|
||||
.map(|e| e.to_string())
|
||||
.unwrap_or_else(|| "Unknown error occurred".to_string());
|
||||
println!("Error response: {:?}", error);
|
||||
tauri::async_runtime::spawn( async move {
|
||||
if let Err(e) = window.emit(event_name, ChunkPayload{ request_id, chunk: error.into() }) {
|
||||
println!("Failed to emit chunk payload: {:?}", e);
|
||||
}
|
||||
if let Err(e) = window.emit(event_name, EndPayload{ request_id, status: 0 }) {
|
||||
println!("Failed to emit end payload: {:?}", e);
|
||||
}
|
||||
});
|
||||
StreamResponse {
|
||||
request_id,
|
||||
status: 599,
|
||||
status_text: "Error".to_string(),
|
||||
headers: HashMap::new(),
|
||||
}
|
||||
}
|
||||
};
|
||||
// println!("Response: {:?}", response);
|
||||
Ok(response)
|
||||
}
|
||||
|
@ -1,120 +0,0 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"build": {
|
||||
"beforeBuildCommand": "yarn export",
|
||||
"beforeDevCommand": "yarn export:dev",
|
||||
"devPath": "http://localhost:3000",
|
||||
"distDir": "../out",
|
||||
"withGlobalTauri": true
|
||||
},
|
||||
"package": {
|
||||
"productName": "NextChat",
|
||||
"version": "2.15.8"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"shell": {
|
||||
"all": false,
|
||||
"open": true
|
||||
},
|
||||
"dialog": {
|
||||
"all": true,
|
||||
"ask": true,
|
||||
"confirm": true,
|
||||
"message": true,
|
||||
"open": true,
|
||||
"save": true
|
||||
},
|
||||
"clipboard": {
|
||||
"all": true,
|
||||
"writeText": true,
|
||||
"readText": true
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"setIcon": true,
|
||||
"setIgnoreCursorEvents": true,
|
||||
"setResizable": true,
|
||||
"show": true,
|
||||
"startDragging": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true
|
||||
},
|
||||
"fs": {
|
||||
"all": true
|
||||
},
|
||||
"notification": {
|
||||
"all": true
|
||||
},
|
||||
"http": {
|
||||
"all": true,
|
||||
"request": true,
|
||||
"scope": ["https://*", "http://*"]
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "2023, Zhang Yifei All Rights Reserved.",
|
||||
"deb": {
|
||||
"depends": []
|
||||
},
|
||||
"externalBin": [],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"identifier": "com.yida.chatgpt.next.web",
|
||||
"longDescription": "NextChat is a cross-platform ChatGPT client, including Web/Win/Linux/OSX/PWA.",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "NextChat App",
|
||||
"targets": "all",
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"csp": null,
|
||||
"dangerousUseHttpScheme": true
|
||||
},
|
||||
"updater": {
|
||||
"active": true,
|
||||
"endpoints": [
|
||||
"https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/releases/latest/download/latest.json"
|
||||
],
|
||||
"dialog": true,
|
||||
"windows": {
|
||||
"installMode": "passive"
|
||||
},
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IERFNDE4MENFM0Y1RTZBOTQKUldTVWFsNC96b0JCM3RqM2NmMnlFTmxIaStRaEJrTHNOU2VqRVlIV1hwVURoWUdVdEc1eDcxVEYK"
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"title": "NextChat",
|
||||
"width": 960,
|
||||
"hiddenTitle": true,
|
||||
"titleBarStyle": "Overlay"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|