mirror of
https://github.com/wisdgod/cursor-api.git
synced 2025-10-09 08:30:06 +08:00
v0.1.3-rc.3
This commit is contained in:
332
src/app/model.rs
Normal file
332
src/app/model.rs
Normal file
@@ -0,0 +1,332 @@
|
||||
use crate::{
|
||||
app::constant::{
|
||||
ERR_INVALID_PATH, ERR_RESET_CONFIG, ERR_UPDATE_CONFIG, ROUTE_ABOUT_PATH, ROUTE_CONFIG_PATH,
|
||||
ROUTE_LOGS_PATH, ROUTE_README_PATH, ROUTE_ROOT_PATH, ROUTE_SHARED_JS_PATH,
|
||||
ROUTE_SHARED_STYLES_PATH, ROUTE_TOKENINFO_PATH,
|
||||
},
|
||||
common::models::usage::UserUsageInfo,
|
||||
};
|
||||
use crate::chat::model::Message;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::RwLock;
|
||||
|
||||
// 页面内容类型枚举
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", content = "content")]
|
||||
pub enum PageContent {
|
||||
#[serde(rename = "default")]
|
||||
Default, // 默认行为
|
||||
#[serde(rename = "text")]
|
||||
Text(String), // 纯文本
|
||||
#[serde(rename = "html")]
|
||||
Html(String), // HTML 内容
|
||||
}
|
||||
|
||||
impl Default for PageContent {
|
||||
fn default() -> Self {
|
||||
Self::Default
|
||||
}
|
||||
}
|
||||
|
||||
mod usage_check;
|
||||
pub use usage_check::UsageCheck;
|
||||
|
||||
// 静态配置
|
||||
#[derive(Clone)]
|
||||
pub struct AppConfig {
|
||||
stream_check: bool,
|
||||
stop_stream: bool,
|
||||
vision_ability: VisionAbility,
|
||||
slow_pool: bool,
|
||||
allow_claude: bool,
|
||||
pages: Pages,
|
||||
usage_check: UsageCheck,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub enum VisionAbility {
|
||||
#[serde(rename = "none", alias = "disabled")]
|
||||
None,
|
||||
#[serde(rename = "base64", alias = "base64-only")]
|
||||
Base64,
|
||||
#[serde(rename = "all", alias = "base64-http")]
|
||||
All,
|
||||
}
|
||||
|
||||
impl VisionAbility {
|
||||
pub fn from_str(s: &str) -> Self {
|
||||
match s.to_lowercase().as_str() {
|
||||
"none" | "disabled" => Self::None,
|
||||
"base64" | "base64-only" => Self::Base64,
|
||||
"all" | "base64-http" => Self::All,
|
||||
_ => Self::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VisionAbility {
|
||||
fn default() -> Self {
|
||||
Self::Base64
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Pages {
|
||||
pub root_content: PageContent,
|
||||
pub logs_content: PageContent,
|
||||
pub config_content: PageContent,
|
||||
pub tokeninfo_content: PageContent,
|
||||
pub shared_styles_content: PageContent,
|
||||
pub shared_js_content: PageContent,
|
||||
pub about_content: PageContent,
|
||||
pub readme_content: PageContent,
|
||||
}
|
||||
|
||||
// 运行时状态
|
||||
pub struct AppState {
|
||||
pub total_requests: u64,
|
||||
pub active_requests: u64,
|
||||
pub request_logs: Vec<RequestLog>,
|
||||
pub token_infos: Vec<TokenInfo>,
|
||||
}
|
||||
|
||||
// 全局配置实例
|
||||
lazy_static! {
|
||||
pub static ref APP_CONFIG: RwLock<AppConfig> = RwLock::new(AppConfig::default());
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
stream_check: true,
|
||||
stop_stream: true,
|
||||
vision_ability: VisionAbility::Base64,
|
||||
slow_pool: false,
|
||||
allow_claude: false,
|
||||
pages: Pages::default(),
|
||||
usage_check: UsageCheck::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! config_methods {
|
||||
($($field:ident: $type:ty, $default:expr;)*) => {
|
||||
$(
|
||||
paste::paste! {
|
||||
pub fn [<get_ $field>]() -> $type {
|
||||
APP_CONFIG
|
||||
.read()
|
||||
.map(|config| config.$field.clone())
|
||||
.unwrap_or($default)
|
||||
}
|
||||
|
||||
pub fn [<update_ $field>](value: $type) -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.$field = value;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_UPDATE_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn [<reset_ $field>]() -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.$field = $default;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_RESET_CONFIG)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
pub fn init(
|
||||
stream_check: bool,
|
||||
stop_stream: bool,
|
||||
vision_ability: VisionAbility,
|
||||
slow_pool: bool,
|
||||
allow_claude: bool,
|
||||
) {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.stream_check = stream_check;
|
||||
config.stop_stream = stop_stream;
|
||||
config.vision_ability = vision_ability;
|
||||
config.slow_pool = slow_pool;
|
||||
config.allow_claude = allow_claude;
|
||||
}
|
||||
}
|
||||
|
||||
config_methods! {
|
||||
stream_check: bool, true;
|
||||
stop_stream: bool, true;
|
||||
slow_pool: bool, false;
|
||||
allow_claude: bool, false;
|
||||
}
|
||||
|
||||
pub fn get_vision_ability() -> VisionAbility {
|
||||
APP_CONFIG
|
||||
.read()
|
||||
.map(|config| config.vision_ability.clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn get_page_content(path: &str) -> Option<PageContent> {
|
||||
APP_CONFIG.read().ok().map(|config| match path {
|
||||
ROUTE_ROOT_PATH => config.pages.root_content.clone(),
|
||||
ROUTE_LOGS_PATH => config.pages.logs_content.clone(),
|
||||
ROUTE_CONFIG_PATH => config.pages.config_content.clone(),
|
||||
ROUTE_TOKENINFO_PATH => config.pages.tokeninfo_content.clone(),
|
||||
ROUTE_SHARED_STYLES_PATH => config.pages.shared_styles_content.clone(),
|
||||
ROUTE_SHARED_JS_PATH => config.pages.shared_js_content.clone(),
|
||||
ROUTE_ABOUT_PATH => config.pages.about_content.clone(),
|
||||
ROUTE_README_PATH => config.pages.readme_content.clone(),
|
||||
_ => PageContent::default(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_usage_check() -> UsageCheck {
|
||||
APP_CONFIG
|
||||
.read()
|
||||
.map(|config| config.usage_check.clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn update_vision_ability(new_ability: VisionAbility) -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.vision_ability = new_ability;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_UPDATE_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_page_content(path: &str, content: PageContent) -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
match path {
|
||||
ROUTE_ROOT_PATH => config.pages.root_content = content,
|
||||
ROUTE_LOGS_PATH => config.pages.logs_content = content,
|
||||
ROUTE_CONFIG_PATH => config.pages.config_content = content,
|
||||
ROUTE_TOKENINFO_PATH => config.pages.tokeninfo_content = content,
|
||||
ROUTE_SHARED_STYLES_PATH => config.pages.shared_styles_content = content,
|
||||
ROUTE_SHARED_JS_PATH => config.pages.shared_js_content = content,
|
||||
ROUTE_ABOUT_PATH => config.pages.about_content = content,
|
||||
ROUTE_README_PATH => config.pages.readme_content = content,
|
||||
_ => return Err(ERR_INVALID_PATH),
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_UPDATE_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_usage_check(rule: UsageCheck) -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.usage_check = rule;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_UPDATE_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_vision_ability() -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.vision_ability = VisionAbility::Base64;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_RESET_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_page_content(path: &str) -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
match path {
|
||||
ROUTE_ROOT_PATH => config.pages.root_content = PageContent::default(),
|
||||
ROUTE_LOGS_PATH => config.pages.logs_content = PageContent::default(),
|
||||
ROUTE_CONFIG_PATH => config.pages.config_content = PageContent::default(),
|
||||
ROUTE_TOKENINFO_PATH => config.pages.tokeninfo_content = PageContent::default(),
|
||||
ROUTE_SHARED_STYLES_PATH => {
|
||||
config.pages.shared_styles_content = PageContent::default()
|
||||
}
|
||||
ROUTE_SHARED_JS_PATH => config.pages.shared_js_content = PageContent::default(),
|
||||
ROUTE_ABOUT_PATH => config.pages.about_content = PageContent::default(),
|
||||
ROUTE_README_PATH => config.pages.readme_content = PageContent::default(),
|
||||
_ => return Err(ERR_INVALID_PATH),
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_RESET_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_usage_check() -> Result<(), &'static str> {
|
||||
if let Ok(mut config) = APP_CONFIG.write() {
|
||||
config.usage_check = UsageCheck::default();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ERR_RESET_CONFIG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new(token_infos: Vec<TokenInfo>) -> Self {
|
||||
Self {
|
||||
total_requests: 0,
|
||||
active_requests: 0,
|
||||
request_logs: Vec::new(),
|
||||
token_infos,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 请求日志
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct RequestLog {
|
||||
pub timestamp: chrono::DateTime<chrono::Local>,
|
||||
pub model: String,
|
||||
pub token_info: TokenInfo,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub prompt: Option<String>,
|
||||
pub stream: bool,
|
||||
pub status: &'static str,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
// pub struct PromptList(Option<String>);
|
||||
|
||||
// impl PromptList {
|
||||
// pub fn to_vec(&self) -> Vec<>
|
||||
// }
|
||||
|
||||
// 聊天请求
|
||||
#[derive(Deserialize)]
|
||||
pub struct ChatRequest {
|
||||
pub model: String,
|
||||
pub messages: Vec<Message>,
|
||||
#[serde(default)]
|
||||
pub stream: bool,
|
||||
}
|
||||
|
||||
// 用于存储 token 信息
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct TokenInfo {
|
||||
pub token: String,
|
||||
pub checksum: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub alias: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub usage: Option<UserUsageInfo>,
|
||||
}
|
||||
|
||||
// TokenUpdateRequest 结构体
|
||||
#[derive(Deserialize)]
|
||||
pub struct TokenUpdateRequest {
|
||||
pub tokens: String,
|
||||
#[serde(default)]
|
||||
pub token_list: Option<String>,
|
||||
}
|
Reference in New Issue
Block a user