Persist accumulated session cost

This commit is contained in:
Tyler Yust
2026-03-12 16:21:09 -07:00
parent 02d5c07e62
commit cfef9d5d45
12 changed files with 342 additions and 69 deletions

View File

@@ -1753,6 +1753,91 @@ describe("persistSessionUsageUpdate", () => {
expect(stored[sessionKey].totalTokens).toBe(250_000);
expect(stored[sessionKey].totalTokensFresh).toBe(true);
});
it("accumulates estimatedCostUsd across persisted usage updates", async () => {
const storePath = await createStorePath("openclaw-usage-cost-");
const sessionKey = "main";
await seedSessionStore({
storePath,
sessionKey,
entry: {
sessionId: "s1",
updatedAt: Date.now(),
estimatedCostUsd: 0.0015,
},
});
await persistSessionUsageUpdate({
storePath,
sessionKey,
cfg: {
models: {
providers: {
openai: {
models: [
{
id: "gpt-5.4",
label: "GPT 5.4",
baseUrl: "https://api.openai.com/v1",
cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.5 },
},
],
},
},
},
} as OpenClawConfig,
usage: { input: 2_000, output: 500, cacheRead: 1_000, cacheWrite: 200 },
lastCallUsage: { input: 800, output: 200, cacheRead: 300, cacheWrite: 50 },
providerUsed: "openai",
modelUsed: "gpt-5.4",
contextTokensUsed: 200_000,
});
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
expect(stored[sessionKey].estimatedCostUsd).toBeCloseTo(0.009225, 8);
});
it("persists zero estimatedCostUsd for free priced models", async () => {
const storePath = await createStorePath("openclaw-usage-free-cost-");
const sessionKey = "main";
await seedSessionStore({
storePath,
sessionKey,
entry: {
sessionId: "s1",
updatedAt: Date.now(),
},
});
await persistSessionUsageUpdate({
storePath,
sessionKey,
cfg: {
models: {
providers: {
"openai-codex": {
models: [
{
id: "gpt-5.3-codex-spark",
label: "GPT 5.3 Codex Spark",
baseUrl: "https://api.openai.com/v1",
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
},
],
},
},
},
} as OpenClawConfig,
usage: { input: 5_107, output: 1_827, cacheRead: 1_536, cacheWrite: 0 },
lastCallUsage: { input: 5_107, output: 1_827, cacheRead: 1_536, cacheWrite: 0 },
providerUsed: "openai-codex",
modelUsed: "gpt-5.3-codex-spark",
contextTokensUsed: 200_000,
});
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
expect(stored[sessionKey].estimatedCostUsd).toBe(0);
});
});
describe("initSessionState stale threadId fallback", () => {