fix: use backend thread token usage for header total (#2800)

* fix: use backend thread token usage for header total

* Refactor thread token usage fetch
This commit is contained in:
YuJitang
2026-05-09 19:40:32 +08:00
committed by GitHub
parent 881ff71252
commit 417416087b
16 changed files with 540 additions and 35 deletions
@@ -0,0 +1,51 @@
import { beforeEach, expect, test, vi } from "vitest";
const fetchWithAuth = vi.fn();
vi.mock("@/core/api/fetcher", () => ({
fetch: fetchWithAuth,
}));
beforeEach(() => {
fetchWithAuth.mockReset();
});
test("fetchThreadTokenUsage uses shared auth fetch without JSON GET headers", async () => {
fetchWithAuth.mockResolvedValue({
ok: true,
json: async () => ({
thread_id: "thread-1",
total_input_tokens: 3,
total_output_tokens: 4,
total_tokens: 7,
total_runs: 1,
by_model: { unknown: { tokens: 7, runs: 1 } },
by_caller: {},
}),
});
const { fetchThreadTokenUsage } = await import("@/core/threads/api");
await expect(fetchThreadTokenUsage("thread-1")).resolves.toMatchObject({
thread_id: "thread-1",
total_tokens: 7,
});
expect(fetchWithAuth).toHaveBeenCalledWith(
expect.stringContaining("/api/threads/thread-1/token-usage"),
{
method: "GET",
},
);
});
test("fetchThreadTokenUsage returns null for unavailable token usage", async () => {
fetchWithAuth.mockResolvedValue({
ok: false,
status: 404,
});
const { fetchThreadTokenUsage } = await import("@/core/threads/api");
await expect(fetchThreadTokenUsage("thread-1")).resolves.toBeNull();
});
@@ -0,0 +1,31 @@
import { expect, test } from "vitest";
import { threadTokenUsageToTokenUsage } from "@/core/threads/token-usage";
import type { ThreadTokenUsageResponse } from "@/core/threads/types";
test("maps backend thread token usage to UI token usage", () => {
const response: ThreadTokenUsageResponse = {
thread_id: "thread-1",
total_input_tokens: 90,
total_output_tokens: 60,
total_tokens: 150,
total_runs: 2,
by_model: { unknown: { tokens: 150, runs: 2 } },
by_caller: {
lead_agent: 120,
subagent: 25,
middleware: 5,
},
};
expect(threadTokenUsageToTokenUsage(response)).toEqual({
inputTokens: 90,
outputTokens: 60,
totalTokens: 150,
});
});
test("returns null when backend thread token usage is unavailable", () => {
expect(threadTokenUsageToTokenUsage(null)).toBeNull();
expect(threadTokenUsageToTokenUsage(undefined)).toBeNull();
});