diff --git a/src/infra/provider-usage.fetch.deepseek.test.ts b/src/infra/provider-usage.fetch.deepseek.test.ts index 45de98abe161..241eb0e41b8d 100644 --- a/src/infra/provider-usage.fetch.deepseek.test.ts +++ b/src/infra/provider-usage.fetch.deepseek.test.ts @@ -85,6 +85,18 @@ describe("fetchDeepSeekUsage", () => { expect(result.windows).toHaveLength(0); }); + it.each([ + ["null response", null], + ["array response", []], + ])("treats %s as absent balance data", async (_name, payload) => { + const mockFetch = createProviderUsageFetch(async () => makeResponse(200, payload)); + + const result = await fetchDeepSeekUsage("deepseek-key", 5000, mockFetch); + + expect(result.error).toBe("No balance data"); + expect(result.windows).toHaveLength(0); + }); + it("marks unavailable accounts while keeping the balance summary", async () => { const mockFetch = createProviderUsageFetch(async () => makeResponse(200, { diff --git a/src/infra/provider-usage.fetch.deepseek.ts b/src/infra/provider-usage.fetch.deepseek.ts index f4e4ffd54188..3bdeac54428d 100644 --- a/src/infra/provider-usage.fetch.deepseek.ts +++ b/src/infra/provider-usage.fetch.deepseek.ts @@ -1,4 +1,5 @@ // Fetches and normalizes DeepSeek provider usage records. +import { isRecord } from "@openclaw/normalization-core/record-coerce"; import { buildUsageHttpErrorSnapshot, discardUsageResponseBody, @@ -86,8 +87,8 @@ export async function fetchDeepSeekUsage( return parsed.snapshot; } - const data = parsed.data as DeepSeekBalanceResponse; - const balances = Array.isArray(data.balance_infos) ? data.balance_infos : []; + const data = isRecord(parsed.data) ? (parsed.data as DeepSeekBalanceResponse) : undefined; + const balances = data && Array.isArray(data.balance_infos) ? data.balance_infos : []; const summary = balances .map((info) => buildBalanceSummary(info)) .filter((entry): entry is string => Boolean(entry)) @@ -120,6 +121,6 @@ export async function fetchDeepSeekUsage( windows: [], billing, summary, - ...(data.is_available === false ? { plan: "Unavailable" } : {}), + ...(data?.is_available === false ? { plan: "Unavailable" } : {}), }; }