0.3.6: WIP

This commit is contained in:
wisdgod
2025-07-27 08:46:05 +08:00
parent c3bfb3b66e
commit c1a7dd1acb
438 changed files with 169172 additions and 15998 deletions

View File

@@ -1,231 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "get-token"
version = "0.1.0"
dependencies = [
"base64",
"rusqlite",
"serde_json",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "hashlink"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
dependencies = [
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "libsqlite3-sys"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "proc-macro2"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rusqlite"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e"
dependencies = [
"bitflags",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"smallvec",
]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "syn"
version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -0,0 +1,23 @@
[package]
name = "next_reload"
version = "0.1.0"
edition = "2024"
[dependencies]
chrono = { version = "0.4", default-features = false, features = ["now", "clock"] }
[patch.crates-io]
chrono = { path = "../../patch/chrono-0.4.41" }
[profile.release]
lto = true
codegen-units = 1
panic = 'abort'
strip = true
# debug = true
# split-debuginfo = 'packed'
# strip = "none"
# panic = 'unwind'
opt-level = 3
trim-paths = "all"
rustflags = ["-Cdebuginfo=0", "-Zthreads=8"]

View File

@@ -0,0 +1,55 @@
use ::std::borrow::Cow;
use ::chrono::{DateTime, TimeDelta, Local, TimeZone as _, Utc};
/// 获取下一个整千秒的时间点
fn next_thousand_second_mark() -> DateTime<Utc> {
let now = Utc::now();
let timestamp = now.timestamp();
let current_thousand = timestamp / 1000;
let next_thousand_timestamp = (current_thousand + 1) * 1000;
Utc.timestamp_opt(next_thousand_timestamp, 0)
.single()
.expect("valid timestamp")
}
/// 格式化剩余时间为人类可读格式
fn format_duration(duration: TimeDelta) -> Cow<'static, str> {
let total_seconds = duration.num_seconds();
if total_seconds <= 0 {
return Cow::Borrowed("已到达");
}
let hours = total_seconds / 3600;
let minutes = (total_seconds % 3600) / 60;
let seconds = total_seconds % 60;
Cow::Owned(if hours > 0 {
format!("{hours} 小时 {minutes} 分钟 {seconds}")
} else if minutes > 0 {
format!("{minutes} 分钟 {seconds}")
} else {
format!("{seconds}")
})
}
fn main() {
let now_local = Local::now();
let next_mark_utc = next_thousand_second_mark();
let next_mark_local = next_mark_utc.with_timezone(&Local);
let remaining = next_mark_utc - Utc::now();
println!("当前时间: {}", now_local.format("%Y-%m-%d %H:%M:%S"));
println!(
"下一个整千秒时刻: {}",
next_mark_local.format("%Y-%m-%d %H:%M:%S")
);
println!("距离下一个整千秒还有: {}", format_duration(remaining));
println!("\n详细信息:");
println!("- 当前时间戳: {}", now_local.timestamp());
println!("- 下一个整千秒时间戳: {}", next_mark_utc.timestamp());
}

View File

@@ -1,273 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "reset-telemetry"
version = "0.1.0"
dependencies = [
"rand",
"serde_json",
"sha2",
"uuid",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "uuid"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
dependencies = [
"getrandom",
]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -0,0 +1,430 @@
use std::{
collections::{HashMap, HashSet},
fs::OpenOptions,
path::PathBuf,
sync::LazyLock,
};
use chrono::{DateTime, Local};
use memmap2::{MmapMut, MmapOptions};
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[derive(Clone, Archive, RkyvSerialize, RkyvDeserialize)]
pub struct TokenInfo {
pub alias: Option<String>,
pub token: String,
pub checksum: Checksum,
pub status: TokenStatus,
pub client_key: Hash,
pub config_version: Option<uuid::Uuid>,
pub session_id: Option<uuid::Uuid>,
pub profile: Option<TokenProfile>,
pub tags: Option<HashMap<String, Option<String>>>,
}
#[derive(Clone, Archive, RkyvSerialize, RkyvDeserialize)]
pub struct OldTokenInfo {
pub token: String,
pub checksum: Checksum,
pub status: OldTokenStatus,
pub client_key: Hash,
pub config_version: Option<uuid::Uuid>,
pub session_id: Option<uuid::Uuid>,
pub profile: Option<TokenProfile>,
pub tags: Option<HashMap<String, Option<String>>>,
}
impl From<OldTokenInfo> for TokenInfo {
fn from(value: OldTokenInfo) -> Self {
Self {
alias: if let Some(profile) = &value.profile {
Some(profile.user.email.clone())
} else {
None
},
token: value.token,
checksum: value.checksum,
status: value.status.into(),
client_key: value.client_key,
config_version: value.config_version,
session_id: value.session_id,
profile: value.profile,
tags: value.tags,
}
}
}
#[derive(Clone, Copy, Archive, RkyvSerialize, RkyvDeserialize)]
pub struct Checksum {
first: Hash,
second: Hash,
}
#[derive(Default, Clone, Copy, Archive, RkyvSerialize, RkyvDeserialize)]
#[repr(u8)]
pub enum OldTokenStatus {
#[default]
Enabled,
Disabled,
}
#[derive(Default, Clone, Copy, Archive, RkyvSerialize, RkyvDeserialize)]
#[repr(u8)]
pub enum TokenStatus {
#[default]
Enabled,
Disabled,
Hidden,
}
impl From<OldTokenStatus> for TokenStatus {
fn from(value: OldTokenStatus) -> Self {
match value {
OldTokenStatus::Enabled => TokenStatus::Enabled,
OldTokenStatus::Disabled => TokenStatus::Disabled,
}
}
}
#[derive(Clone, Copy, Archive, RkyvSerialize, RkyvDeserialize)]
#[repr(transparent)]
pub struct Hash([u8; 32]);
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct TokenProfile {
pub usage: UsageProfile,
pub user: UserProfile,
pub stripe: StripeProfile,
}
#[derive(PartialEq, Clone, Copy, Archive, RkyvDeserialize, RkyvSerialize)]
pub enum MembershipType {
Free,
FreeTrial,
Pro,
Enterprise,
}
impl std::str::FromStr for MembershipType {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"free" => Ok(MembershipType::Free),
"free_trial" => Ok(MembershipType::FreeTrial),
"pro" => Ok(MembershipType::Pro),
"enterprise" => Ok(MembershipType::Enterprise),
_ => Err(()),
}
}
}
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct StripeProfile {
pub membership_type: MembershipType,
pub payment_id: Option<String>,
pub days_remaining_on_trial: u32,
}
#[derive(Clone, Copy, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct ModelUsage {
pub num_requests: u32,
pub total_requests: Option<u32>,
pub num_tokens: u32,
pub max_requests: Option<u32>,
pub max_tokens: Option<u32>,
}
#[derive(Clone, Copy, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct UsageProfile {
pub premium: ModelUsage,
pub standard: ModelUsage,
pub unknown: ModelUsage,
pub start_of_month: DateTime<Local>,
}
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct UserProfile {
pub email: String,
// pub email_verified: bool,
pub name: String,
pub sub: String,
pub updated_at: DateTime<Local>,
// Image link, rendered in /logs?
// pub picture: Option<String>,
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
enum ErrorInfoHelper {
None,
Error(String),
Details { error: String, details: String },
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
pub struct RequestLogHelper {
id: u64,
timestamp: chrono::DateTime<chrono::Local>,
model: String,
token_info: TokenInfo,
chain: Option<ChainHelper>,
timing: TimingInfo,
stream: bool,
status: LogStatus,
error: ErrorInfoHelper,
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
pub struct OldRequestLogHelper {
id: u64,
timestamp: chrono::DateTime<chrono::Local>,
model: String,
token_info: OldTokenInfo,
chain: Option<ChainHelper>,
timing: TimingInfo,
stream: bool,
status: LogStatus,
error: ErrorInfoHelper,
}
impl From<OldRequestLogHelper> for RequestLogHelper {
fn from(value: OldRequestLogHelper) -> Self {
Self {
id: value.id,
timestamp: value.timestamp,
model: value.model,
token_info: {
let value = value.token_info;
TokenInfo {
alias: None,
token: value.token,
checksum: value.checksum,
status: value.status.into(),
client_key: value.client_key,
config_version: value.config_version,
session_id: value.session_id,
profile: value.profile,
tags: value.tags,
}
},
chain: value.chain,
timing: value.timing,
stream: value.stream,
status: value.status,
error: value.error,
}
}
}
impl OldRequestLogHelper {
fn load_logs() -> Result<Vec<Self>, Box<dyn std::error::Error>> {
let file = match OpenOptions::new().read(true).open(&*LOGS_FILE_PATH) {
Ok(file) => file,
Err(e) => return Err(Box::new(e)),
};
if file.metadata()?.len() > usize::MAX as u64 {
return Err("日志文件过大".into());
}
let mmap = unsafe { MmapOptions::new().map(&file)? };
let archived = unsafe { rkyv::archived_root::<Vec<Self>>(&mmap) };
let helper: Vec<Self> = archived.deserialize(&mut rkyv::Infallible)?;
Ok(helper)
}
}
impl RequestLogHelper {
fn save_logs(logs: Vec<Self>) -> Result<(), Box<dyn std::error::Error>> {
let bytes = rkyv::to_bytes::<_, 256>(&logs)?;
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&*LOGS_FILE_PATH)?;
if bytes.len() > usize::MAX >> 1 {
return Err("日志数据过大".into());
}
file.set_len(bytes.len() as u64)?;
let mut mmap = unsafe { MmapMut::map_mut(&file)? };
mmap.copy_from_slice(&bytes);
mmap.flush()?;
Ok(())
}
}
#[derive(Clone, Copy, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct TimingInfo {
pub total: f64, // 总用时(秒)
}
#[derive(Clone, Copy, PartialEq, Archive, RkyvDeserialize, RkyvSerialize)]
#[repr(u8)]
pub enum LogStatus {
Pending,
Success,
Failure,
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
pub struct PromptMessageHelper {
role: Role,
content: String,
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize, Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum Role {
System = 0u8,
User,
Assistant,
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
pub enum PromptHelper {
None,
Origin(String),
Parsed(Vec<PromptMessageHelper>),
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
pub struct ChainHelper {
pub prompt: PromptHelper,
pub delays: Option<(String, Vec<(u32, f32)>)>,
pub usage: OptionUsage,
pub think: Option<String>,
}
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub enum OptionUsage {
None,
Uasge { input: i32, output: i32 },
}
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct TokenManager {
pub tokens: Vec<TokenInfo>,
pub aliases: HashSet<String>,
pub tags: HashSet<String>,
}
#[derive(Clone, Archive, RkyvDeserialize, RkyvSerialize)]
pub struct OldTokenManager {
pub tokens: Vec<OldTokenInfo>,
pub tags: HashSet<String>,
}
impl From<OldTokenManager> for TokenManager {
fn from(value: OldTokenManager) -> Self {
let tokens: Vec<TokenInfo> = value.tokens.into_iter().map(Into::into).collect();
let mut aliases = HashSet::new();
let mut tags = HashSet::new();
for token in &tokens {
if let Some(token_tags) = &token.tags {
tags.extend(token_tags.keys().cloned());
}
if let Some(alias) = &token.alias {
aliases.insert(alias.clone());
}
}
Self {
tokens,
aliases,
tags,
}
}
}
impl OldTokenManager {
fn load_tokens() -> Result<Self, Box<dyn std::error::Error>> {
let file = match OpenOptions::new().read(true).open(&*TOKENS_FILE_PATH) {
Ok(file) => file,
Err(e) => return Err(Box::new(e)),
};
if file.metadata()?.len() > usize::MAX as u64 {
return Err("Token文件过大".into());
}
let mmap = unsafe { MmapOptions::new().map(&file)? };
let archived = unsafe { rkyv::archived_root::<Self>(&mmap) };
Ok(archived.deserialize(&mut rkyv::Infallible)?)
}
}
impl TokenManager {
fn save_tokens(&self) -> Result<(), Box<dyn std::error::Error>> {
let bytes = rkyv::to_bytes::<_, 256>(self)?;
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&*TOKENS_FILE_PATH)?;
if bytes.len() > usize::MAX >> 1 {
return Err("Token数据过大".into());
}
file.set_len(bytes.len() as u64)?;
let mut mmap = unsafe { MmapMut::map_mut(&file)? };
mmap.copy_from_slice(&bytes);
mmap.flush()?;
Ok(())
}
}
static DATA_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
let data_dir = std::env::var("DATA_DIR").unwrap_or_else(|_| "data".to_string());
let path = std::env::current_exe()
.ok()
.and_then(|exe_path| exe_path.parent().map(|p| p.to_path_buf()))
.unwrap_or_else(|| PathBuf::from("."))
.join(data_dir);
if !path.exists() {
std::fs::create_dir_all(&path).expect("无法创建数据目录");
}
path
});
static LOGS_FILE_PATH: LazyLock<PathBuf> = LazyLock::new(|| DATA_DIR.join("logs.bin"));
static TOKENS_FILE_PATH: LazyLock<PathBuf> = LazyLock::new(|| DATA_DIR.join("tokens.bin"));
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 设置自定义 panic hook
std::panic::set_hook(Box::new(|info| {
if let Some(msg) = info.payload().downcast_ref::<String>() {
eprintln!("{msg}");
} else if let Some(msg) = info.payload().downcast_ref::<&str>() {
eprintln!("{msg}");
}
}));
// 加载环境变量
dotenvy::dotenv().ok();
// 添加交互式询问
println!("是否确定使用数据适配器(cursor-api附属工具)将v0.2.8迁移至v0.2.9?(此操作不可撤销)");
println!(
"Are you sure to use data adapter (cursor-api auxiliary tool) to migrate from v0.2.8 to v0.2.9? (This operation is irreversible)"
);
let mut input = String::new();
println!(
"请输入 'y'/'yes' 确认或 'n'/'no' 取消 (Please enter 'y'/'yes' to confirm or 'n'/'no' to cancel):"
);
std::io::stdin().read_line(&mut input)?;
let input = input.trim().to_lowercase();
if input != "y" && input != "yes" {
println!("操作已取消 (Operation cancelled)");
return Ok(());
}
// 执行迁移
let old = OldTokenManager::load_tokens()?;
let new: TokenManager = old.into();
new.save_tokens()?;
let old = OldRequestLogHelper::load_logs()?;
let new: Vec<RequestLogHelper> = old.into_iter().map(Into::into).collect();
RequestLogHelper::save_logs(new)?;
println!("数据迁移成功完成 (Data migration completed successfully)");
Ok(())
}

View File

@@ -1,219 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "foldhash"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [
"foldhash",
]
[[package]]
name = "hashlink"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
dependencies = [
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "libsqlite3-sys"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rusqlite"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c6d5e5acb6f6129fe3f7ba0a7fc77bca1942cb568535e18e7bc40262baf3110"
dependencies = [
"bitflags",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"smallvec",
]
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "set-token"
version = "0.1.0"
dependencies = [
"regex",
"rusqlite",
"serde_json",
]
[[package]]
name = "smallvec"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]]
name = "syn"
version = "2.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"