Skip to content

fix(teams): expose keys_count on /v2/team/list and wire UI Resources badge#28502

Merged
Sameerlite merged 1 commit into
litellm_internal_stagingfrom
litellm_fix_v2_team_list_keys_count
May 29, 2026
Merged

fix(teams): expose keys_count on /v2/team/list and wire UI Resources badge#28502
Sameerlite merged 1 commit into
litellm_internal_stagingfrom
litellm_fix_v2_team_list_keys_count

Conversation

@michelligabriele

Copy link
Copy Markdown
Collaborator

Relevant issues

N/A

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

Verification against a proxy with two teams (team A with 3 virtual keys, team B with 0):

```

  1. /v2/team/list?team_id=<team_a> (single-team filter)
    {
    "team_id": "f2eabc73-ac0b-4885-8871-4b30226a2336",
    "team_alias": "verify-keys-count-A-...",
    "members_count": 1,
    "keys_count": 3
    }

  2. /v2/team/list (full page, both teams visible)
    {
    "team_id": "2419f752-...",
    "team_alias": "verify-keys-count-B-...",
    "keys_count": 0
    }
    {
    "team_id": "f2eabc73-...",
    "team_alias": "verify-keys-count-A-...",
    "keys_count": 3
    }
    ```

Before this change, `/v2/team/list` did not expose any per-team key count, so the Teams page Resources badge (which fell back to `team.keys.length`) always rendered `0 Keys` — even on teams that owned virtual keys (the per-team detail Virtual Keys tab was unaffected since it uses `/key/list?team_id=…`).

Type

🐛 Bug Fix

Changes

  • Add `keys_count: int = 0` to `TeamListItem` so the paginated team-list response carries an authoritative per-team key count.
  • Populate `keys_count` in `list_team_v2` via a single batched Prisma `group_by` against `LiteLLM_VerificationToken` for the current page's team IDs. The `IN` clause is bounded by `page_size` and uses the existing `@@index([team_id])`, so this is one DB round-trip per page (cheaper than the legacy `/team/list`'s per-team N+1 `find_many`).
  • Thread an optional `keys_count_by_team` map through `_convert_teams_to_response_models`; the existing caller's behavior is unchanged (default empty → `0` for all teams). The deleted-table branch is skipped — `LiteLLM_DeletedTeamTable` does not carry `keys_count`.
  • UI (Teams list): read `keys_count` from the v2 payload for the Resources column's keys badge, with a `keys.length` fallback for backwards compatibility. Touches `OldTeams.tsx`, `TeamsView.tsx`, `TeamsTable.tsx`, and the shared `Team` interface in `key_list.tsx`.
  • UI (delete-team modal): switch the "Warning: this team has N keys" banner and the resource-information row to read `keys_count`, restoring the keys-warning variant that was no longer firing after the v2 migration.
  • Tests:
    • `tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py` — 3 new async tests covering the happy path (`keys_count` populated from the batched group_by), the empty-page short-circuit (no group_by issued), and the deleted-status branch (no group_by issued). Existing `list_team_v2` tests get a `litellm_verificationtoken.group_by` stub so they don't trip on the new call.
    • `ui/litellm-dashboard/src/components/OldTeams.test.tsx` — 2 new render tests asserting the Resources badge picks up `keys_count` from the v2 payload and falls back to `keys.length` when absent.

@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the /v2/team/list endpoint returning 0 for the per-team key count by adding a single batched group_by against LiteLLM_VerificationToken for each page of teams, and wires the new keys_count field through to all relevant UI components.

  • Backend: keys_count: int = 0 added to TeamListItem; list_team_v2 issues one group_by per page (bounded by page_size, skipped for empty pages and the deleted-team branch), matching the existing pattern in spend_management_endpoints.py.
  • UI: OldTeams.tsx, TeamsView.tsx, and TeamsTable.tsx all read keys_count first with a keys.length fallback; the delete-modal warning banner and resource-information row are updated consistently; new render tests cover both the v2 path and the fallback.

Confidence Score: 5/5

Safe to merge — the change is purely additive on the backend and fully backwards-compatible in the UI.

The batched group_by query follows the established pattern in spend_management_endpoints.py, the empty-page and deleted-table short-circuits are correctly guarded, and all three UI display sites are updated consistently. The keys.length fallback preserves compatibility with older API responses.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/team_endpoints.py Adds a single group_by query on LiteLLM_VerificationToken to aggregate per-team key counts for the current page; result is passed into _convert_teams_to_response_models which threads it into TeamListItem.keys_count. Logic is sound — empty-page and deleted-table branches correctly skip the DB call.
litellm/types/proxy/management_endpoints/team_endpoints.py Adds keys_count: int = 0 to TeamListItem with a safe default — additive, backwards-compatible schema change.
tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py Adds 3 new unit tests (happy path, empty page, deleted-status) and stubs group_by on 4 existing tests that would otherwise break. New mocks correctly match the actual group_by call signature and return format.
ui/litellm-dashboard/src/components/OldTeams.tsx Reads keys_count (with keys.length fallback) for the Resources column badge, the delete-modal warning banner, and the resource-information row. Logic covers all three display sites consistently.
ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/TeamsTable.tsx Replaces the keys.length chain with keys_count from PerTeamInfo; ?? 0 fallback correctly handles undefined and falsy-but-valid 0 counts.
ui/litellm-dashboard/src/components/key_team_helpers/key_list.tsx Adds keys_count?: number as an optional field to the Team interface — non-breaking addition.
ui/litellm-dashboard/src/components/OldTeams.test.tsx Adds 2 render tests asserting the cyan Keys badge displays keys_count from the v2 payload and falls back to keys.length when absent.

Reviews (2): Last reviewed commit: "fix(teams ui): add keys_count to TeamsTa..." | Re-trigger Greptile

Comment thread litellm/proxy/management_endpoints/team_endpoints.py Outdated

@Sameerlite Sameerlite left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

# GROUP BY. The IN clause is bounded by page_size and uses the existing
# @@index([team_id]) on LiteLLM_VerificationToken.
keys_count_by_team: Dict[str, int] = {}
if not use_deleted_table:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you put this logic into a method?

@Sameerlite

Copy link
Copy Markdown
Collaborator

@greptileai

@Sameerlite

Copy link
Copy Markdown
Collaborator

Also, can you check the failing mock tests? Thanks!

@michelligabriele michelligabriele force-pushed the litellm_fix_v2_team_list_keys_count branch from 3bd52c1 to 7ec8109 Compare May 28, 2026 21:45

@Sameerlite Sameerlite left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Sameerlite Sameerlite merged commit 68852ef into litellm_internal_staging May 29, 2026
115 of 118 checks passed
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants