diff --git a/packages/ai/src/auth-storage.ts b/packages/ai/src/auth-storage.ts index 1f1c60529..cd3f87990 100644 --- a/packages/ai/src/auth-storage.ts +++ b/packages/ai/src/auth-storage.ts @@ -2185,7 +2185,7 @@ export class AuthStorage { recordUsageCost( provider: Provider, costUsd: number, - options?: { sessionId?: string; recordedAt?: number }, + options?: { sessionId?: string; recordedAt?: number; baseUrl?: string }, ): boolean { if (!Number.isFinite(costUsd) || costUsd <= 0) return false; const record = this.#store.recordUsageCosts; @@ -2200,6 +2200,13 @@ export class AuthStorage { }; try { record.call(this.#store, [entry]); + const cacheKey = this.#buildUsageReportCacheKey({ + provider, + credential, + baseUrl: options?.baseUrl, + }); + const existing = this.#usageCache.getStale(cacheKey); + this.#usageCache.set(cacheKey, { value: existing?.value ?? null, expiresAt: Date.now() - 1 }); return true; } catch (error) { this.#usageLogger?.debug("usage cost record failed", { diff --git a/packages/ai/test/auth-storage-usage-history.test.ts b/packages/ai/test/auth-storage-usage-history.test.ts index a0035c7f8..28659bc63 100644 --- a/packages/ai/test/auth-storage-usage-history.test.ts +++ b/packages/ai/test/auth-storage-usage-history.test.ts @@ -219,6 +219,21 @@ describe("OpenCode Go usage from observed request costs", () => { ]); }); + it("refreshes cached OpenCode Go limits after recording new observed spend", async () => { + const nowMs = Date.parse("2026-06-18T12:00:00Z"); + setSystemTime(new Date(nowMs)); + + const initialReports = await storage.fetchUsageReports(); + const initial = initialReports?.find(candidate => candidate.provider === "opencode-go"); + expect(initial?.limits.find(limit => limit.id === "rolling-5h")?.amount.used).toBe(0); + + storage.recordUsageCost("opencode-go", 3, { recordedAt: nowMs }); + + const refreshedReports = await storage.fetchUsageReports(); + const refreshed = refreshedReports?.find(candidate => candidate.provider === "opencode-go"); + expect(refreshed?.limits.find(limit => limit.id === "rolling-5h")?.amount.used).toBe(3); + }); + it("aggregates one key's observed spend into OpenCode Go cap windows", async () => { const nowMs = Date.parse("2026-06-18T12:00:00Z"); setSystemTime(new Date(nowMs)); diff --git a/packages/coding-agent/src/session/agent-session.ts b/packages/coding-agent/src/session/agent-session.ts index af2d61655..89eb0d8f0 100644 --- a/packages/coding-agent/src/session/agent-session.ts +++ b/packages/coding-agent/src/session/agent-session.ts @@ -2503,6 +2503,7 @@ export class AgentSession { this.#modelRegistry.authStorage.recordUsageCost(assistantMsg.provider, assistantMsg.usage.cost.total, { sessionId: this.#activeProviderSessionId(), recordedAt: assistantMsg.timestamp, + baseUrl: this.#modelRegistry.getProviderBaseUrl?.(assistantMsg.provider), }); } }