Repository navigation
feat(usage): add a Usage tab with provider limits and usage history #2225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
KarthickMahalingam
wants to merge
37
commits into
Zoo-Code-Org:main
Choose a base branch
from
KarthickMahalingam:feat/usage-tab
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+8,776
−27
Open
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
a0aa52a
feat(usage): add a Usage tab with provider limits and usage history
KarthickMahalingam c0891e4
fix(types): add apiProvider and modelId to ClineApiReqInfo
KarthickMahalingam a7ba4ad
test(visual): add Usage tab baselines
KarthickMahalingam 0774432
fix(usage): wrap long text instead of clipping it at the reflow width
KarthickMahalingam 010a565
fix(usage): address review feedback on quotas, cache hit rate, and retry
KarthickMahalingam 56a7085
fix(usage): reconcile condense cost and record the resolved model
KarthickMahalingam a2cf471
fix(usage): use the provider registry in a test; refresh baselines fo…
KarthickMahalingam dafd502
fix(usage): cancel Copilot quota lookups with the request, unique req…
KarthickMahalingam cda3475
test(usage): require exactly one quota call, and avoid a racy dynamic…
KarthickMahalingam f263acf
style: format Task.spec
KarthickMahalingam ae50b61
fix(usage): do not join a cancelled quota request; ignore non-finite …
KarthickMahalingam 9191d4a
fix(usage): clear a stale usageByModel when messages are replaced; cl…
KarthickMahalingam 56d07b1
test: use providerIdentifiers in the usageByModel store test
KarthickMahalingam 017237c
fix(usage): cancel profile loading and the Copilot token stage; add s…
KarthickMahalingam ed9657f
fix(usage): compute metadata from the persisted (merged) messages; as…
KarthickMahalingam f19d08a
refactor(usage): remove guards made unreachable by the abortable waits
KarthickMahalingam 094138b
Merge branch 'main' into feat/usage-tab
KarthickMahalingam cb58245
Merge branch 'main' into feat/usage-tab
KarthickMahalingam ab61e55
test(usage): pin the cache lifetime and hostile base URLs; report a C…
KarthickMahalingam a6a594c
feat(usage): translate the names of fixed provider-limit windows
KarthickMahalingam 3074d68
Merge branch 'main' into feat/usage-tab
KarthickMahalingam 361be13
test(usage): cover the day-count window name
KarthickMahalingam 1586ed0
Merge branch 'main' into feat/usage-tab
KarthickMahalingam bcb4e40
Merge branch 'main' into feat/usage-tab
KarthickMahalingam dc9d128
fix(usage): record the serving handler per request; OpenRouter total …
KarthickMahalingam ef34663
Merge branch 'main' into feat/usage-tab
KarthickMahalingam f616c70
fix(lint): hold the served model id in an object, not a let that is a…
KarthickMahalingam 34335c4
fix(usage): skip non-object stored requests; abort quota requests on …
KarthickMahalingam a7b0743
fix(usage): query the active profile's own credentials; deadline for …
KarthickMahalingam d66e03d
fix(ci): add the new export to the handler mock; drop the unused load…
KarthickMahalingam 89025cc
Merge branch 'main' into feat/usage-tab
KarthickMahalingam e544e9c
fix(usage): keep another key's cache entry; abort on sidebar dispose;…
KarthickMahalingam 3c06690
Merge branch 'main' into feat/usage-tab
KarthickMahalingam 51fbd59
Merge branch 'main' into feat/usage-tab
KarthickMahalingam c27fe1d
fix(usage): inert CSV counters; an explicit usage clear wins over ano…
KarthickMahalingam e65ba25
fix(usage): one selection for the totals and the CSV; stronger assert…
KarthickMahalingam e545685
fix(usage): leave out times a date cannot represent; the cost-only re…
KarthickMahalingam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
src/core/task-persistence/__tests__/taskMetadata.usageByModel.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import { describe, expect, it, vi } from "vitest" | ||
|
|
||
| import { providerIdentifiers, type ClineMessage } from "@roo-code/types" | ||
|
|
||
| vi.mock("get-folder-size", () => ({ default: { loose: vi.fn(async () => 1234) } })) | ||
| vi.mock("../../../utils/storage", () => ({ getTaskDirectoryPath: vi.fn(async () => "/tmp/task") })) | ||
| vi.mock("../../../i18n", () => ({ t: (k: string) => k })) | ||
|
|
||
| import { taskMetadata } from "../taskMetadata" | ||
|
|
||
| const say = (say: ClineMessage["say"], text: string, ts: number): ClineMessage => ({ ts, type: "say", say, text }) | ||
|
|
||
| const base = { | ||
| taskId: "t1", | ||
| taskNumber: 1, | ||
| globalStoragePath: "/tmp", | ||
| workspace: "/ws", | ||
| } | ||
|
|
||
| describe("taskMetadata – usageByModel", () => { | ||
| it("records per provider+model usage on the history item", async () => { | ||
| const messages = [ | ||
| say("text", "do the thing", 1), | ||
| say( | ||
| "api_req_started", | ||
| JSON.stringify({ | ||
| apiProvider: providerIdentifiers.githubCopilot, | ||
| modelId: "claude-opus-5.5", | ||
| tokensIn: 900, | ||
| tokensOut: 90, | ||
| cost: 0, | ||
| }), | ||
| 2, | ||
| ), | ||
| say( | ||
| "api_req_started", | ||
| JSON.stringify({ | ||
| apiProvider: providerIdentifiers.gemini, | ||
| modelId: "gemini-pro", | ||
| tokensIn: 100, | ||
| tokensOut: 10, | ||
| cost: 0.2, | ||
| }), | ||
| 3, | ||
| ), | ||
| ] | ||
| const { historyItem } = await taskMetadata({ ...base, messages }) | ||
|
|
||
| expect(historyItem.usageByModel).toEqual([ | ||
| { | ||
| apiProvider: providerIdentifiers.githubCopilot, | ||
| modelId: "claude-opus-5.5", | ||
| requests: 1, | ||
| tokensIn: 900, | ||
| tokensOut: 90, | ||
| cost: 0, | ||
| }, | ||
| { | ||
| apiProvider: providerIdentifiers.gemini, | ||
| modelId: "gemini-pro", | ||
| requests: 1, | ||
| tokensIn: 100, | ||
| tokensOut: 10, | ||
| cost: 0.2, | ||
| }, | ||
| ]) | ||
| // Existing totals are unchanged by the new breakdown. | ||
| expect(historyItem.tokensIn).toBe(1000) | ||
| expect(historyItem.totalCost).toBeCloseTo(0.2) | ||
| }) | ||
|
|
||
| it("leaves usageByModel undefined when nothing was recorded, so a stored breakdown is cleared", async () => { | ||
| const { historyItem } = await taskMetadata({ ...base, messages: [say("text", "hello", 1)] }) | ||
| expect(historyItem).toHaveProperty("usageByModel", undefined) | ||
| // Nothing is written for it: the stored shape of older tasks is unchanged. | ||
| expect(JSON.parse(JSON.stringify(historyItem))).not.toHaveProperty("usageByModel") | ||
| }) | ||
|
|
||
| it("leaves usageByModel undefined for a task with no messages", async () => { | ||
| const { historyItem } = await taskMetadata({ ...base, messages: [] }) | ||
| expect(historyItem).toHaveProperty("usageByModel", undefined) | ||
| expect(historyItem.tokensIn).toBe(0) | ||
| }) | ||
| }) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.