


























@@ -724,6 +724,72 @@ describe("session cost usage", () => {
724724});
725725});
726726727+it("reclaims stale usage cache temp files before refreshing", async () => {
728+const root = await makeSessionCostRoot("cost-cache-temp-cleanup");
729+const sessionsDir = path.join(root, "agents", "main", "sessions");
730+await fs.mkdir(sessionsDir, { recursive: true });
731+const sessionFile = path.join(sessionsDir, "sess-cache-temp-cleanup.jsonl");
732+await fs.writeFile(
733+sessionFile,
734+transcriptText("sess-cache-temp-cleanup", {
735+type: "message",
736+timestamp: "2026-02-05T12:00:00.000Z",
737+message: {
738+role: "assistant",
739+provider: "openai",
740+model: "gpt-5.4",
741+usage: {
742+input: 10,
743+output: 20,
744+totalTokens: 30,
745+cost: { total: 0.03 },
746+},
747+},
748+}),
749+"utf-8",
750+);
751+752+const staleLegacyTempPath = path.join(sessionsDir, ".usage-cost-cache.json.12345.tmp");
753+const staleCurrentTempPath = path.join(sessionsDir, ".usage-cost-cache.12345.tmp");
754+const recentTempPath = path.join(sessionsDir, ".usage-cost-cache.67890.tmp");
755+const lockTempPath = path.join(sessionsDir, ".usage-cost-cache.json.lock.12345.tmp");
756+await Promise.all(
757+[staleLegacyTempPath, staleCurrentTempPath, recentTempPath, lockTempPath].map((tempPath) =>
758+fs.writeFile(tempPath, "partial\n", "utf-8"),
759+),
760+);
761+const staleTime = new Date(Date.now() - 60_000);
762+await Promise.all(
763+[staleLegacyTempPath, staleCurrentTempPath, lockTempPath].map((tempPath) =>
764+fs.utimes(tempPath, staleTime, staleTime),
765+),
766+);
767+768+const exists = async (filePath: string): Promise<boolean> =>
769+await fs.stat(filePath).then(
770+() => true,
771+() => false,
772+);
773+774+await withStateDir(root, async () => {
775+const result = await refreshCostUsageCache();
776+expect(result).toBe("refreshed");
777+778+expect(await exists(staleLegacyTempPath)).toBe(false);
779+expect(await exists(staleCurrentTempPath)).toBe(false);
780+expect(await exists(recentTempPath)).toBe(true);
781+expect(await exists(lockTempPath)).toBe(true);
782+783+const summary = await loadCostUsageSummaryFromCache({
784+startMs: Date.UTC(2026, 1, 5),
785+endMs: Date.UTC(2026, 1, 5) + 24 * 60 * 60 * 1000 - 1,
786+requestRefresh: false,
787+});
788+expect(summary.totals.totalTokens).toBe(30);
789+expect(summary.cacheStatus?.status).toBe("fresh");
790+});
791+});
792+727793it("keeps queued durable aggregate refresh state scoped to the cache path", async () => {
728794const firstRoot = await makeSessionCostRoot("cost-cache-queued-first");
729795const secondRoot = await makeSessionCostRoot("cost-cache-queued-second");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。