Compare commits

...
3 Commits
Author SHA1 Message Date
KimiSwitch Dev 86112ee90b chore(release): bump to v0.7.14 — 修复关闭用量查询后仍查询/报错的问题
Release / Version consistency (push) Canceled after 0s
Release / Build (macos-latest) (push) Canceled after 0s
Release / Build (ubuntu-latest) (push) Canceled after 0s
Release / Build (windows-latest) (push) Canceled after 0s
Release / Attach macOS install script (push) Canceled after 0s
2026-09-06 19:38:13 +08:00
KimiSwitch Dev e349fa5971 chore(data): 同步 models-dev 快照价格漂移 2026-09-06 19:36:44 +08:00
KimiSwitch Dev 1de8b9ee4c fix(usage): 关闭「启用用量查询」后不再发起查询且隐藏用量行
useUsageQuery 增加 disabled 门控:关闭时自动查询不发、refresh no-op、
状态立即复位 idle(UsageFooter 对 idle 返回 null,compact/detail 均
整体隐藏);在途响应按 generation 作废且不写入模块级共享缓存,
避免关闭瞬间的失败结果在 5 分钟内重新挂载时复活。
2026-09-06 19:36:42 +08:00
9 changed files with 178669 additions and 176699 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "kimiswitch", "name": "kimiswitch",
"private": true, "private": true,
"version": "0.7.13", "version": "0.7.14",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+10
View File
@@ -0,0 +1,10 @@
# KimiSwitch v0.7.14
## 修复
- **关闭「启用用量查询」后不再残留查询行为**:此前关闭开关后前端仍会发起查询,卡片上持续显示「查询失败 · 用量查询已关闭」的红色错误行。现在关闭后立即停止查询、隐藏整行用量信息(卡片头部与底部两种展示均生效),重新开启后自动恢复
- 在途的查询结果在开关切换瞬间作废,且不再写入共享缓存,避免过期的失败状态在 5 分钟内复活
## 数据
- models-dev 快照同步(上游格式与价格更新)
+1 -1
View File
@@ -1978,7 +1978,7 @@ dependencies = [
[[package]] [[package]]
name = "kimiswitch" name = "kimiswitch"
version = "0.7.13" version = "0.7.14"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "kimiswitch" name = "kimiswitch"
version = "0.7.13" version = "0.7.14"
description = "Kimi Switch - model config manager" description = "Kimi Switch - model config manager"
authors = ["codingplan.site"] authors = ["codingplan.site"]
edition = "2021" edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"productName": "Kimi Switch", "productName": "Kimi Switch",
"version": "0.7.13", "version": "0.7.14",
"identifier": "com.kimiswitch.app", "identifier": "com.kimiswitch.app",
"build": { "build": {
"beforeDevCommand": "npm run dev", "beforeDevCommand": "npm run dev",
+2 -1
View File
@@ -69,7 +69,8 @@ function ProviderCard({
agent, agent,
provider.name, provider.name,
provider.usageKinds, provider.usageKinds,
provider.usageConfig?.autoQueryIntervalMinutes provider.usageConfig?.autoQueryIntervalMinutes,
provider.usageConfig?.enabled === false
); );
const providerModels = Object.values(models).filter( const providerModels = Object.values(models).filter(
(m) => m.provider === provider.name (m) => m.provider === provider.name
+18 -6
View File
@@ -62,7 +62,8 @@ export function useUsageQuery(
agent: Agent, agent: Agent,
providerName: string, providerName: string,
usageKinds?: string[], usageKinds?: string[],
autoIntervalMinutes?: number autoIntervalMinutes?: number,
disabled?: boolean
): UsageQueryState { ): UsageQueryState {
const supported = (usageKinds?.length ?? 0) > 0; const supported = (usageKinds?.length ?? 0) > 0;
// Cache key includes the agent so a Kimi Code provider and a Pi provider // Cache key includes the agent so a Kimi Code provider and a Pi provider
@@ -79,12 +80,13 @@ export function useUsageQuery(
const runQuery = useCallback( const runQuery = useCallback(
async (forceRefresh: boolean) => { async (forceRefresh: boolean) => {
if (disabled) return;
const gen = ++genRef.current; const gen = ++genRef.current;
setStatus("loading"); setStatus("loading");
setError(undefined); setError(undefined);
const finish = (entry: CacheEntry) => { const finish = (entry: CacheEntry) => {
cache.set(cacheKey, entry);
if (genRef.current !== gen) return; if (genRef.current !== gen) return;
cache.set(cacheKey, entry);
setStatus(entry.status); setStatus(entry.status);
setData(entry.data); setData(entry.data);
setError(entry.error); setError(entry.error);
@@ -129,11 +131,21 @@ export function useUsageQuery(
}); });
} }
}, },
[agent, providerName, cacheKey] [agent, providerName, cacheKey, disabled]
); );
// On mount / provider change: serve fresh cache, otherwise query once. // On mount / provider change: serve fresh cache, otherwise query once.
useEffect(() => { useEffect(() => {
if (disabled) {
// Toggle back off: stop immediately and return to idle so the footer
// hides; bump gen so an in-flight response is dropped (no stale write).
genRef.current += 1;
setStatus("idle");
setData([]);
setError(undefined);
setUpdatedAt(null);
return;
}
if (!supported) return; if (!supported) return;
const cached = cache.get(cacheKey); const cached = cache.get(cacheKey);
if (cached) { if (cached) {
@@ -144,7 +156,7 @@ export function useUsageQuery(
if (Date.now() - cached.updatedAt < STALE_TTL_MS) return; if (Date.now() - cached.updatedAt < STALE_TTL_MS) return;
} }
void runQuery(false); void runQuery(false);
}, [supported, cacheKey, runQuery]); }, [supported, cacheKey, runQuery, disabled]);
// Ignore late responses after unmount. // Ignore late responses after unmount.
useEffect(() => { useEffect(() => {
@@ -156,12 +168,12 @@ export function useUsageQuery(
// Auto query interval — the hook is called once per provider card and both // Auto query interval — the hook is called once per provider card and both
// variants read the same state, so there is no second mount to double-fire. // variants read the same state, so there is no second mount to double-fire.
useEffect(() => { useEffect(() => {
if (!supported) return; if (!supported || disabled) return;
const mins = autoIntervalMinutes ?? 0; const mins = autoIntervalMinutes ?? 0;
if (mins <= 0) return; if (mins <= 0) return;
const id = setInterval(() => void runQuery(false), mins * 60_000); const id = setInterval(() => void runQuery(false), mins * 60_000);
return () => clearInterval(id); return () => clearInterval(id);
}, [supported, autoIntervalMinutes, runQuery]); }, [supported, autoIntervalMinutes, runQuery, disabled]);
return { return {
status, status,
+98116 -97072
View File
File diff suppressed because it is too large. Load diff
+80519 -79616
View File
File diff suppressed because it is too large. Load diff