fix: resolve rustfmt formatting and clippy warnings

- Apply cargo fmt across schema.rs, session_usage*.rs, skill.rs, usage_stats.rs
- Fix clippy::for_kv_map: use messages.values() instead of (_, msg) pattern
- Suppress clippy::only_used_in_recursion for intentional recursive base path
- Fix prettier formatting in UsageScriptModal.tsx
This commit is contained in:
Jason
2026-04-06 23:37:35 +08:00
parent d33d63e4df
commit 697d0dd6e1
7 changed files with 150 additions and 102 deletions
+73 -12
View File
@@ -1128,9 +1128,7 @@ impl Database {
WHERE model_id = ?1",
rusqlite::params![model_id, input, output, cache_read, cache_creation],
)
.map_err(|e| {
AppError::Database(format!("更新模型 {model_id} 定价失败: {e}"))
})?;
.map_err(|e| AppError::Database(format!("更新模型 {model_id} 定价失败: {e}")))?;
}
log::info!("v7 -> v8 迁移完成:data_source 列、session_log_sync 表、修正 13 个模型定价");
@@ -1457,7 +1455,14 @@ impl Database {
"0",
),
// Gemini 2.0 系列
("gemini-2.0-flash", "Gemini 2.0 Flash", "0.10", "0.40", "0.025", "0"),
(
"gemini-2.0-flash",
"Gemini 2.0 Flash",
"0.10",
"0.40",
"0.025",
"0",
),
// StepFun 系列
(
"step-3.5-flash",
@@ -1469,17 +1474,66 @@ impl Database {
),
// ====== 国产模型 (USD/1M tokens) ======
// Doubao (字节跳动)
("doubao-seed-code", "Doubao Seed Code", "0.17", "1.11", "0.02", "0"),
(
"doubao-seed-code",
"Doubao Seed Code",
"0.17",
"1.11",
"0.02",
"0",
),
// DeepSeek 系列
("deepseek-v3.2", "DeepSeek V3.2", "0.28", "0.42", "0.028", "0"),
("deepseek-v3.1", "DeepSeek V3.1", "0.55", "1.67", "0.055", "0"),
(
"deepseek-v3.2",
"DeepSeek V3.2",
"0.28",
"0.42",
"0.028",
"0",
),
(
"deepseek-v3.1",
"DeepSeek V3.1",
"0.55",
"1.67",
"0.055",
"0",
),
("deepseek-v3", "DeepSeek V3", "0.28", "1.11", "0.028", "0"),
("deepseek-chat", "DeepSeek Chat", "0.28", "0.42", "0.028", "0"),
("deepseek-reasoner", "DeepSeek Reasoner", "0.28", "0.42", "0.028", "0"),
(
"deepseek-chat",
"DeepSeek Chat",
"0.28",
"0.42",
"0.028",
"0",
),
(
"deepseek-reasoner",
"DeepSeek Reasoner",
"0.28",
"0.42",
"0.028",
"0",
),
// Kimi (月之暗面)
("kimi-k2-thinking", "Kimi K2 Thinking", "0.55", "2.20", "0.10", "0"),
(
"kimi-k2-thinking",
"Kimi K2 Thinking",
"0.55",
"2.20",
"0.10",
"0",
),
("kimi-k2-0905", "Kimi K2", "0.55", "2.20", "0.10", "0"),
("kimi-k2-turbo", "Kimi K2 Turbo", "1.11", "8.06", "0.14", "0"),
(
"kimi-k2-turbo",
"Kimi K2 Turbo",
"1.11",
"8.06",
"0.14",
"0",
),
("kimi-k2.5", "Kimi K2.5", "0.60", "3.00", "0.10", "0"),
// MiniMax 系列
("minimax-m2.1", "MiniMax M2.1", "0.27", "0.95", "0.03", "0"),
@@ -1496,7 +1550,14 @@ impl Database {
("glm-4.7", "GLM-4.7", "0.39", "1.75", "0.04", "0"),
("glm-4.6", "GLM-4.6", "0.28", "1.11", "0.03", "0"),
// Mimo (小米)
("mimo-v2-flash", "Mimo V2 Flash", "0.09", "0.29", "0.009", "0"),
(
"mimo-v2-flash",
"Mimo V2 Flash",
"0.09",
"0.29",
"0.009",
"0",
),
];
for (model_id, display_name, input, output, cache_read, cache_creation) in pricing_data {
+23 -23
View File
@@ -155,8 +155,8 @@ fn sync_single_file(db: &Database, file_path: &Path) -> Result<(u32, u32), AppEr
}
// 从上次偏移位置开始增量解析
let file = fs::File::open(file_path)
.map_err(|e| AppError::Config(format!("无法打开文件: {e}")))?;
let file =
fs::File::open(file_path).map_err(|e| AppError::Config(format!("无法打开文件: {e}")))?;
let reader = BufReader::new(file);
let mut line_offset: i64 = 0;
@@ -272,7 +272,7 @@ fn sync_single_file(db: &Database, file_path: &Path) -> Result<(u32, u32), AppEr
let mut imported: u32 = 0;
let mut skipped: u32 = 0;
for (_, msg) in &messages {
for msg in messages.values() {
// 只导入有 stop_reason 的最终条目(完整的 API 调用)
if msg.stop_reason.is_none() {
continue;
@@ -383,26 +383,26 @@ fn insert_session_log_entry(
let pricing = find_model_pricing_for_session(&conn, &msg.model);
let multiplier = Decimal::from(1);
let (input_cost, output_cost, cache_read_cost, cache_creation_cost, total_cost) =
match pricing {
Some(p) => {
let cost = CostCalculator::calculate(&usage, &p, multiplier);
(
cost.input_cost.to_string(),
cost.output_cost.to_string(),
cost.cache_read_cost.to_string(),
cost.cache_creation_cost.to_string(),
cost.total_cost.to_string(),
)
}
None => (
"0".to_string(),
"0".to_string(),
"0".to_string(),
"0".to_string(),
"0".to_string(),
),
};
let (input_cost, output_cost, cache_read_cost, cache_creation_cost, total_cost) = match pricing
{
Some(p) => {
let cost = CostCalculator::calculate(&usage, &p, multiplier);
(
cost.input_cost.to_string(),
cost.output_cost.to_string(),
cost.cache_read_cost.to_string(),
cost.cache_creation_cost.to_string(),
cost.total_cost.to_string(),
)
}
None => (
"0".to_string(),
"0".to_string(),
"0".to_string(),
"0".to_string(),
"0".to_string(),
),
};
conn.execute(
"INSERT OR IGNORE INTO proxy_request_logs (
@@ -746,7 +746,10 @@ mod tests {
#[test]
fn test_normalize_codex_model_strip_prefix() {
assert_eq!(normalize_codex_model("openai/gpt-5.4"), "gpt-5.4");
assert_eq!(normalize_codex_model("azure/gpt-5.2-codex"), "gpt-5.2-codex");
assert_eq!(
normalize_codex_model("azure/gpt-5.2-codex"),
"gpt-5.2-codex"
);
assert_eq!(normalize_codex_model("OPENAI/GPT-5.4"), "gpt-5.4");
}
@@ -784,10 +787,7 @@ mod tests {
"gpt-5.4"
);
// prefix + compact date
assert_eq!(
normalize_codex_model("openai/gpt-5.4-20260305"),
"gpt-5.4"
);
assert_eq!(normalize_codex_model("openai/gpt-5.4-20260305"), "gpt-5.4");
}
#[test]
@@ -799,7 +799,7 @@ mod tests {
output: 50,
});
let current = CumulativeTokens {
input: 110, // delta = 10
input: 110, // delta = 10
cached_input: 80, // delta = 80(异常:大于 input delta
output: 60,
};
+10 -22
View File
@@ -182,10 +182,7 @@ fn sync_single_gemini_file(db: &Database, file_path: &Path) -> Result<(u32, u32)
gemini_msg_count += 1;
// 提取消息 ID 和模型
let message_id = msg
.get("id")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let message_id = msg.get("id").and_then(|v| v.as_str()).unwrap_or("unknown");
let model = msg
.get("model")
.and_then(|v| v.as_str())
@@ -222,22 +219,10 @@ fn sync_single_gemini_file(db: &Database, file_path: &Path) -> Result<(u32, u32)
/// 从 tokens JSON 对象中提取 token 数据
fn parse_gemini_tokens(tokens: &serde_json::Value) -> GeminiTokens {
GeminiTokens {
input: tokens
.get("input")
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32,
output: tokens
.get("output")
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32,
cached: tokens
.get("cached")
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32,
thoughts: tokens
.get("thoughts")
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32,
input: tokens.get("input").and_then(|v| v.as_u64()).unwrap_or(0) as u32,
output: tokens.get("output").and_then(|v| v.as_u64()).unwrap_or(0) as u32,
cached: tokens.get("cached").and_then(|v| v.as_u64()).unwrap_or(0) as u32,
thoughts: tokens.get("thoughts").and_then(|v| v.as_u64()).unwrap_or(0) as u32,
}
}
@@ -494,7 +479,9 @@ mod tests {
assert_eq!(tokens.input, 0);
assert_eq!(tokens.output, 0);
// 全零(包括 cached=0)会被 sync 逻辑跳过
assert!(tokens.input == 0 && tokens.output == 0 && tokens.thoughts == 0 && tokens.cached == 0);
assert!(
tokens.input == 0 && tokens.output == 0 && tokens.thoughts == 0 && tokens.cached == 0
);
}
#[test]
@@ -509,7 +496,8 @@ mod tests {
let tokens = parse_gemini_tokens(&json);
assert_eq!(tokens.cached, 5000);
// 跳过条件:所有四个字段都为 0 才跳过
let should_skip = tokens.input == 0 && tokens.output == 0 && tokens.thoughts == 0 && tokens.cached == 0;
let should_skip =
tokens.input == 0 && tokens.output == 0 && tokens.thoughts == 0 && tokens.cached == 0;
assert!(!should_skip, "纯缓存命中记录不应被跳过");
}
}
+2 -4
View File
@@ -854,6 +854,7 @@ impl SkillService {
}
/// 递归收集目录下所有非隐藏文件
#[allow(clippy::only_used_in_recursion)]
fn collect_files_for_hash(base: &Path, current: &Path, files: &mut Vec<PathBuf>) -> Result<()> {
let entries = fs::read_dir(current)
.with_context(|| format!("读取目录失败: {}", current.display()))?;
@@ -2737,10 +2738,7 @@ impl SkillService {
repo_name: repo.clone(),
repo_branch: "main".to_string(),
installs: s.installs,
readme_url: Some(format!(
"https://github.com/{}/{}",
owner, repo
)),
readme_url: Some(format!("https://github.com/{}/{}", owner, repo)),
})
})
.collect();
+34 -33
View File
@@ -383,7 +383,10 @@ impl Database {
let mut rstmt = conn.prepare(&rollup_sql)?;
let rrows = if let Some(at) = app_type {
rstmt.query_map(params![start_ts, end_ts, bucket_seconds, at], rollup_row_mapper)?
rstmt.query_map(
params![start_ts, end_ts, bucket_seconds, at],
rollup_row_mapper,
)?
} else {
rstmt.query_map(params![start_ts, end_ts, bucket_seconds], rollup_row_mapper)?
};
@@ -757,38 +760,36 @@ impl Database {
LEFT JOIN providers p ON l.provider_id = p.id AND l.app_type = p.app_type
WHERE l.request_id = ?"
);
let result = conn.query_row(
&detail_sql,
[request_id],
|row| {
Ok(RequestLogDetail {
request_id: row.get(0)?,
provider_id: row.get(1)?,
provider_name: row.get(2)?,
app_type: row.get(3)?,
model: row.get(4)?,
request_model: row.get(5)?,
cost_multiplier: row.get::<_, Option<String>>(6)?.unwrap_or_else(|| "1".to_string()),
input_tokens: row.get::<_, i64>(7)? as u32,
output_tokens: row.get::<_, i64>(8)? as u32,
cache_read_tokens: row.get::<_, i64>(9)? as u32,
cache_creation_tokens: row.get::<_, i64>(10)? as u32,
input_cost_usd: row.get(11)?,
output_cost_usd: row.get(12)?,
cache_read_cost_usd: row.get(13)?,
cache_creation_cost_usd: row.get(14)?,
total_cost_usd: row.get(15)?,
is_streaming: row.get::<_, i64>(16)? != 0,
latency_ms: row.get::<_, i64>(17)? as u64,
first_token_ms: row.get::<_, Option<i64>>(18)?.map(|v| v as u64),
duration_ms: row.get::<_, Option<i64>>(19)?.map(|v| v as u64),
status_code: row.get::<_, i64>(20)? as u16,
error_message: row.get(21)?,
created_at: row.get(22)?,
data_source: row.get(23)?,
})
},
);
let result = conn.query_row(&detail_sql, [request_id], |row| {
Ok(RequestLogDetail {
request_id: row.get(0)?,
provider_id: row.get(1)?,
provider_name: row.get(2)?,
app_type: row.get(3)?,
model: row.get(4)?,
request_model: row.get(5)?,
cost_multiplier: row
.get::<_, Option<String>>(6)?
.unwrap_or_else(|| "1".to_string()),
input_tokens: row.get::<_, i64>(7)? as u32,
output_tokens: row.get::<_, i64>(8)? as u32,
cache_read_tokens: row.get::<_, i64>(9)? as u32,
cache_creation_tokens: row.get::<_, i64>(10)? as u32,
input_cost_usd: row.get(11)?,
output_cost_usd: row.get(12)?,
cache_read_cost_usd: row.get(13)?,
cache_creation_cost_usd: row.get(14)?,
total_cost_usd: row.get(15)?,
is_streaming: row.get::<_, i64>(16)? != 0,
latency_ms: row.get::<_, i64>(17)? as u64,
first_token_ms: row.get::<_, Option<i64>>(18)?.map(|v| v as u64),
duration_ms: row.get::<_, Option<i64>>(19)?.map(|v| v as u64),
status_code: row.get::<_, i64>(20)? as u16,
error_message: row.get(21)?,
created_at: row.get(22)?,
data_source: row.get(23)?,
})
});
match result {
Ok(mut detail) => {
+2 -2
View File
@@ -1066,7 +1066,7 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
...script,
timeout:
e.target.value === ""
? (("" as unknown) as number)
? ("" as unknown as number)
: Number(e.target.value),
})
}
@@ -1098,7 +1098,7 @@ const UsageScriptModal: React.FC<UsageScriptModalProps> = ({
...script,
autoQueryInterval:
e.target.value === ""
? (("" as unknown) as number)
? ("" as unknown as number)
: Number(e.target.value),
})
}