feat: 新增部分套餐账单查询(v0.6.4)
- 账单/用量查询:balance:kimi(Moonshot 开放平台余额)、NewAPI 中转站余额(accessToken+userId)、Kimi/智谱/MiniMax 套餐档位(5小时/7天) - managed:kimi-code 走 Kimi Code OAuth 登录凭据查询订阅用量,access token 过期自动 refresh 并写回凭据(单 flight 锁 + 写回前重读防 CLI 竞态) - 全屏「配置用量查询」页面:启用开关 / 自动检测 vs NewAPI 模板 / 超时与自动查询间隔 / 测试查询 - 供应商卡片紧凑用量行(切换使用左侧)+ 多档明细行;managed 供应商列表置顶(仅展示层) - 用量显示中英文适配(five_hour→5小时、weekly_limit→7天,Rust 错误串本地化映射) - 修复:usage_kinds serde rename 导致账单入口不显示;测试查询因 save 触发 loading 翻页卸载面板导致结果丢失(silent save)
This commit is contained in:
1 parent
12dcb17771
commit
ace9842556
26 files changed
+1822
-60
No files matched your search
+46
-2
@@ -96,9 +96,17 @@ pub struct Provider {
|
||||
/// `usage_kinds:<provider_name>`, NOT in the agent's config.toml — both
|
||||
/// export paths (kimi_code_io manual TOML, pi_io PiProvider struct) are
|
||||
/// explicit and never serialize this field, while the IPC payload to the
|
||||
/// frontend does carry it.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
/// frontend does carry it. Renamed to camelCase to match the TS
|
||||
/// `Provider.usageKinds` field — without the rename the frontend reads
|
||||
/// `undefined` and no usage footer ever renders.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none", rename = "usageKinds")]
|
||||
pub usage_kinds: Option<Vec<String>>,
|
||||
/// Usage query configuration (template, credentials, auto interval),
|
||||
/// edited via the "配置用量查询" panel. Same persistence strategy as
|
||||
/// `usage_kinds`: SQLite settings `usage_config:<provider_name>`, never
|
||||
/// config.toml; IPC carries it as camelCase.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none", rename = "usageConfig")]
|
||||
pub usage_config: Option<UsageConfig>,
|
||||
}
|
||||
|
||||
impl PartialEq for Provider {
|
||||
@@ -117,6 +125,7 @@ impl PartialEq for Provider {
|
||||
&& self.icon_color == other.icon_color
|
||||
&& self.raw_other == other.raw_other
|
||||
&& self.usage_kinds == other.usage_kinds
|
||||
&& self.usage_config == other.usage_config
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +216,41 @@ impl PartialEq for Config {
|
||||
|
||||
impl Eq for Config {}
|
||||
|
||||
/// Usage query configuration edited via the "配置用量查询" panel.
|
||||
/// Mirrors cc-switch's `UsageScript` but trimmed to what Kimi Switch supports:
|
||||
/// auto-detected kinds plus the NewAPI/OneAPI template. Serialized camelCase
|
||||
/// to match the TS `UsageConfig` interface; persisted in SQLite settings, never
|
||||
/// in the agent's config.toml.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UsageConfig {
|
||||
/// Whether usage queries run for this provider at all.
|
||||
pub enabled: bool,
|
||||
/// "auto" = query the kinds in `usage_kinds` / host detection;
|
||||
/// "newapi" = query a NewAPI/OneAPI gateway with accessToken + userId.
|
||||
pub template_type: String,
|
||||
/// NewAPI query base URL (falls back to the provider's base_url).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub base_url: Option<String>,
|
||||
/// NewAPI web-console access token (NOT the sk- inference key).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub access_token: Option<String>,
|
||||
/// NewAPI user id, sent as the `New-Api-User` header.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub user_id: Option<String>,
|
||||
/// Auto query interval in minutes; 0/None = manual refresh only.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub auto_query_interval_minutes: Option<u32>,
|
||||
/// Per-request timeout in seconds; 0/None = default (8s).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub timeout_seconds: Option<u64>,
|
||||
}
|
||||
|
||||
impl UsageConfig {
|
||||
pub const TEMPLATE_AUTO: &'static str = "auto";
|
||||
pub const TEMPLATE_NEWAPI: &'static str = "newapi";
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Config {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Config")
|
||||
|
||||
Reference in new issue
Block a user