mirror of
https://github.com/wisdgod/cursor-api.git
synced 2025-10-25 08:00:22 +08:00
245 lines
6.2 KiB
Rust
245 lines
6.2 KiB
Rust
use parking_lot::RwLock;
|
||
use std::{
|
||
sync::Arc,
|
||
time::{Duration, Instant},
|
||
};
|
||
|
||
use super::model::Model;
|
||
|
||
macro_rules! def_pub_const {
|
||
($($name:ident => $value:expr),+ $(,)?) => {
|
||
$(
|
||
pub const $name: &'static str = $value;
|
||
)+
|
||
};
|
||
}
|
||
|
||
// 错误信息
|
||
def_pub_const!(
|
||
ERR_UNSUPPORTED_GIF => "不支持动态 GIF",
|
||
ERR_UNSUPPORTED_IMAGE_FORMAT => "不支持的图片格式,仅支持 PNG、JPEG、WEBP 和非动态 GIF",
|
||
ERR_NODATA => "No data",
|
||
);
|
||
|
||
// 系统常量
|
||
pub const MODEL_OBJECT: &str = "model";
|
||
pub const CREATED: &i64 = &1706659200;
|
||
|
||
// AI 服务商
|
||
def_pub_const!(
|
||
ANTHROPIC => "anthropic",
|
||
CURSOR => "cursor",
|
||
GOOGLE => "google",
|
||
OPENAI => "openai",
|
||
DEEPSEEK => "deepseek",
|
||
XAI => "xai",
|
||
UNKNOWN => "unknown",
|
||
);
|
||
|
||
// AI 模型
|
||
def_pub_const!(
|
||
// Anthropic 模型
|
||
CLAUDE_3_OPUS => "claude-3-opus",
|
||
CLAUDE_3_5_SONNET => "claude-3.5-sonnet",
|
||
CLAUDE_3_HAIKU_200K => "claude-3-haiku-200k",
|
||
CLAUDE_3_5_SONNET_200K => "claude-3-5-sonnet-200k",
|
||
CLAUDE_3_5_HAIKU => "claude-3.5-haiku",
|
||
CLAUDE_3_7_SONNET => "claude-3.7-sonnet",
|
||
CLAUDE_3_7_SONNET_THINKING => "claude-3.7-sonnet-thinking",
|
||
CLAUDE_3_7_SONNET_MAX => "claude-3.7-sonnet-max",
|
||
CLAUDE_3_7_SONNET_THINKING_MAX => "claude-3.7-sonnet-thinking-max",
|
||
|
||
// OpenAI 模型
|
||
GPT_4 => "gpt-4",
|
||
GPT_4O => "gpt-4o",
|
||
GPT_3_5_TURBO => "gpt-3.5-turbo",
|
||
GPT_4_TURBO_2024_04_09 => "gpt-4-turbo-2024-04-09",
|
||
GPT_4O_128K => "gpt-4o-128k",
|
||
GPT_4O_MINI => "gpt-4o-mini",
|
||
O1_MINI => "o1-mini",
|
||
O1_PREVIEW => "o1-preview",
|
||
O1 => "o1",
|
||
O3_MINI => "o3-mini",
|
||
GPT_4_5_PREVIEW => "gpt-4.5-preview",
|
||
|
||
// Cursor 模型
|
||
CURSOR_FAST => "cursor-fast",
|
||
CURSOR_SMALL => "cursor-small",
|
||
|
||
// Google 模型
|
||
GEMINI_1_5_FLASH_500K => "gemini-1.5-flash-500k",
|
||
GEMINI_EXP_1206 => "gemini-exp-1206",
|
||
GEMINI_2_0_PRO_EXP => "gemini-2.0-pro-exp",
|
||
GEMINI_2_0_FLASH_THINKING_EXP => "gemini-2.0-flash-thinking-exp",
|
||
GEMINI_2_0_FLASH => "gemini-2.0-flash",
|
||
|
||
// Deepseek 模型
|
||
DEEPSEEK_V3 => "deepseek-v3",
|
||
DEEPSEEK_R1 => "deepseek-r1",
|
||
|
||
// XAI 模型
|
||
GROK_2 => "grok-2",
|
||
|
||
// 未知模型
|
||
DEFAULT => "default",
|
||
);
|
||
|
||
macro_rules! create_models {
|
||
($($model:expr => $owner:expr),* $(,)?) => {
|
||
static INSTANCE: std::sync::LazyLock<RwLock<Models>> = std::sync::LazyLock::new(|| {
|
||
RwLock::new(Models {
|
||
models: Arc::new(vec![
|
||
$(
|
||
Model {
|
||
id: $model,
|
||
created: CREATED,
|
||
object: MODEL_OBJECT,
|
||
owned_by: $owner,
|
||
},
|
||
)*
|
||
]),
|
||
last_update: Instant::now() - Duration::from_secs(30 * 60),
|
||
})
|
||
});
|
||
};
|
||
}
|
||
|
||
pub struct Models {
|
||
pub models: Arc<Vec<Model>>,
|
||
last_update: Instant,
|
||
}
|
||
|
||
impl Models {
|
||
// 返回读锁
|
||
pub fn read() -> parking_lot::RwLockReadGuard<'static, Models> {
|
||
INSTANCE.read()
|
||
}
|
||
|
||
// 返回 Arc 的克隆
|
||
pub fn to_arc() -> Arc<Vec<Model>> {
|
||
INSTANCE.read().models.clone()
|
||
}
|
||
|
||
// 克隆所有模型
|
||
// pub fn cloned() -> Vec<Model> {
|
||
// INSTANCE.read().models.as_ref().clone()
|
||
// }
|
||
|
||
// 检查模型是否存在
|
||
// pub fn exists(model_id: &str) -> bool {
|
||
// Self::read().models.iter().any(|m| m.id == model_id)
|
||
// }
|
||
|
||
// 查找模型并返回其 ID
|
||
pub fn find_id(model: &str) -> Option<&'static str> {
|
||
Self::read()
|
||
.models
|
||
.iter()
|
||
.find(|m| m.id == model)
|
||
.map(|m| m.id)
|
||
}
|
||
|
||
// 返回所有模型 ID 的列表
|
||
pub fn ids() -> Vec<&'static str> {
|
||
Self::read().models.iter().map(|m| m.id).collect()
|
||
}
|
||
|
||
// 写入方法
|
||
pub fn update(new_models: Vec<Model>) -> Result<(), &'static str> {
|
||
if new_models.is_empty() {
|
||
return Err("Models list cannot be empty");
|
||
}
|
||
|
||
let mut data = INSTANCE.write();
|
||
|
||
// 检查时间间隔(30分钟)
|
||
if data.last_update.elapsed() < Duration::from_secs(30 * 60) {
|
||
return Ok(());
|
||
}
|
||
|
||
// 检查内容是否有变化
|
||
if *data.models == new_models {
|
||
return Ok(());
|
||
}
|
||
|
||
// 更新数据和时间戳
|
||
data.models = Arc::new(new_models);
|
||
data.last_update = Instant::now();
|
||
|
||
Ok(())
|
||
}
|
||
}
|
||
|
||
// macro_rules! count {
|
||
// () => (0);
|
||
// (($id:expr, $owner:expr) $( ($id2:expr, $owner2:expr) )*) => (1 + count!($( ($id2, $owner2) )*));
|
||
// }
|
||
|
||
create_models!(
|
||
DEFAULT => UNKNOWN,
|
||
CLAUDE_3_5_SONNET => ANTHROPIC,
|
||
CLAUDE_3_7_SONNET => ANTHROPIC,
|
||
CLAUDE_3_7_SONNET_THINKING => ANTHROPIC,
|
||
CLAUDE_3_7_SONNET_MAX => ANTHROPIC,
|
||
CLAUDE_3_7_SONNET_THINKING_MAX => ANTHROPIC,
|
||
GPT_4 => OPENAI,
|
||
GPT_4O => OPENAI,
|
||
GPT_4_5_PREVIEW => OPENAI,
|
||
CLAUDE_3_OPUS => ANTHROPIC,
|
||
CURSOR_FAST => CURSOR,
|
||
CURSOR_SMALL => CURSOR,
|
||
GPT_3_5_TURBO => OPENAI,
|
||
GPT_4_TURBO_2024_04_09 => OPENAI,
|
||
GPT_4O_128K => OPENAI,
|
||
GEMINI_1_5_FLASH_500K => GOOGLE,
|
||
CLAUDE_3_HAIKU_200K => ANTHROPIC,
|
||
CLAUDE_3_5_SONNET_200K => ANTHROPIC,
|
||
GPT_4O_MINI => OPENAI,
|
||
O1_MINI => OPENAI,
|
||
O1_PREVIEW => OPENAI,
|
||
O1 => OPENAI,
|
||
CLAUDE_3_5_HAIKU => ANTHROPIC,
|
||
GEMINI_2_0_PRO_EXP => GOOGLE,
|
||
GEMINI_2_0_FLASH_THINKING_EXP => GOOGLE,
|
||
GEMINI_2_0_FLASH => GOOGLE,
|
||
DEEPSEEK_V3 => DEEPSEEK,
|
||
DEEPSEEK_R1 => DEEPSEEK,
|
||
O3_MINI => OPENAI,
|
||
GROK_2 => XAI,
|
||
);
|
||
|
||
pub const USAGE_CHECK_MODELS: [&str; 13] = [
|
||
CLAUDE_3_5_SONNET,
|
||
CLAUDE_3_7_SONNET,
|
||
CLAUDE_3_7_SONNET_THINKING,
|
||
GEMINI_EXP_1206,
|
||
GPT_4,
|
||
GPT_4_TURBO_2024_04_09,
|
||
GPT_4O,
|
||
CLAUDE_3_5_HAIKU,
|
||
GPT_4O_128K,
|
||
GEMINI_1_5_FLASH_500K,
|
||
CLAUDE_3_HAIKU_200K,
|
||
CLAUDE_3_5_SONNET_200K,
|
||
DEEPSEEK_R1,
|
||
];
|
||
|
||
pub const LONG_CONTEXT_MODELS: [&str; 4] = [
|
||
GPT_4O_128K,
|
||
GEMINI_1_5_FLASH_500K,
|
||
CLAUDE_3_HAIKU_200K,
|
||
CLAUDE_3_5_SONNET_200K,
|
||
];
|
||
|
||
pub const SUPPORTED_IMAGE_MODELS: [&str; 9] = [
|
||
CLAUDE_3_5_SONNET,
|
||
CLAUDE_3_7_SONNET,
|
||
CLAUDE_3_7_SONNET_THINKING,
|
||
GPT_4O,
|
||
GPT_4O_MINI,
|
||
DEFAULT,
|
||
CLAUDE_3_OPUS,
|
||
CLAUDE_3_5_HAIKU,
|
||
GPT_4,
|
||
];
|