Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(site): show total agent hours consumption on the licenses page - #27953

Merged
jaaydenh merged 20 commits into
mainfrom
agent-hours-card-vky8
Aug 20, 2026
Merged

feat(site): show total agent hours consumption on the licenses page#27953
jaaydenh merged 20 commits into
mainfrom
agent-hours-card-vky8

Conversation

@jaaydenh

@jaaydenh jaaydenh commented Aug 9, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-08-19 at 5 31 17 PM

Adds a "Total agent hours" consumption panel to the Licenses page, surfacing the agent_runtime_hours entitlement introduced by the #27983 / #27984 / #27985 stack.

The new TotalAgentHoursCard renders full width directly above the Agent Workspace Builds panel. It shows a usage bar with Used/Limit labels and an info tooltip next to the title. The bar color and tooltip copy track the same thresholds the backend uses for license warnings: green below the soft limit, orange once usage reaches the soft limit, and red once usage reaches the purchased allocation (values at or beyond the threshold count as reached, matching appendAgentRuntimeHoursWarning). When a soft limit exists, the tooltip states the actual soft-limit percentage computed from soft_limit / limit. The panel is hidden entirely when the feature is disabled, which is how the backend reports a zero-hour allocation.

The usage period dates from Feature.usage_period render above the bar (start left, end right), matching the Agent Workspace Builds panel, so admins can tell which license period the consumption covers. The backend always attaches a period to an enabled feature; a missing or unparsable one just omits the dates row. The CODAGT-855 link to the per-user usage view is deferred: that view (F3, CODAGT-861) and the API it needs (F2, CODAGT-857) are not built yet, so there is no route to target. The link lands with F3.

An enabled feature with limit omitted is the unlimited allocation (license claim -1, coder/license#49): the card shows a full neutral bar with "Limit: Unlimited" and the tooltip without threshold copy, mirroring SeatUsageBarCard's unlimited state. The invalid-limits error is kept for negative limits, which can only come from a decoding bug.

Storybook stories cover the green/orange/red states, the capped over-allocation bar, missing usage data, the missing usage period, the hidden state, the unlimited state, the invalid-limit error state, and each tooltip message via play interactions. The page view story verifies the panel renders above Agent Workspace Builds.

Usage renders with exactly one decimal (e.g. 435.8, 1,000.0), derived from #27985's actual_ms field and floored to tenths with integer math. The same floored value drives the reached states, so the displayed number and the bar color flip at the same instant; a fraction past the allocation now trips the red state (1,000.1 >= 1,000), pinned by the ReachedAllocationByFraction story. The limit and hard cap labels stay whole because the license claims are whole hours.

Stacked on #27985.

closes CODAGT-855.

@linear-code

linear-code Bot commented Aug 9, 2026

Copy link
Copy Markdown

CODAGT-855

@jaaydenh
jaaydenh force-pushed the agent-hours-card-vky8 branch from 65c87f5 to eebd138 Compare August 11, 2026 08:06
@jaaydenh
jaaydenh changed the base branch from entitlements-80f1 to runtime-hours-entitlements August 11, 2026 08:06
@jaaydenh

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eebd138c60

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike 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.

Mux reviewed this pull request on behalf of Mike.

Requesting fixes for two threshold-state defects and a Storybook assertion gap. These are separate from the existing over-allocation tooltip thread.

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 8cbb67945d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jaaydenh

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4fbce07c98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 819e488caf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e5f30d5237

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d2b32e3846

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3cdafa918

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/src/testHelpers/entities.ts Outdated

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e73e2dc97

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 5a96122678

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike 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.

Mux submitted this review on Mike's behalf.

@jaaydenh
jaaydenh force-pushed the agent-hours-card-vky8 branch from 0580b5a to e4f4f1a Compare August 14, 2026 06:31

@ibetitsmike ibetitsmike 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.

Mux reviewed this pull request on Mike's behalf.

Reviewed exact head e4f4f1ae996d9ec03a72e8259491a13c05cc7d0f against the PR merge-base with runtime-hours-entitlements.

Code review

Standards: PASS. The component reuses existing primitives and fixtures, keeps derived state in render, and has comprehensive Storybook interaction coverage.

Spec: one P3 finding. Unlimited, disabled, missing-data, invalid-limit, usage-period, soft-limit, allocation, hard-cap, and fractional-hour states otherwise match the PR description.

P3: Avoid floating-point underflow in displayed percentages

site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/TotalAgentHoursCard.tsx:155

formatPercent floors value * 10, but the input is already a floating-point ratio. For example, (29 / 100) * 100 evaluates to 28.999999999999996, so the tooltip displays 28.9% instead of the exact 29% configured by the integer claims. Similar cases affect 57%, 58%, and other ratios.

Please calculate the tenths percentage from the integer inputs, or otherwise compensate for representation error before flooring. Add a story that uses a ratio such as 29 of 100 and asserts 29%.

Frontend review

FE1 PASS
FE2 PASS
FE3 PASS
FE4 PASS
FE5 PASS
FE6 PASS
FE7 PASS
FE8 PASS
FE9 PASS
FE10 PASS

The two older unresolved GitHub threads are outdated and their reported behaviors are fixed at this head.

Base automatically changed from runtime-hours-entitlements to main August 18, 2026 05:40
@jaaydenh
jaaydenh force-pushed the agent-hours-card-vky8 branch 3 times, most recently from 2468616 to 24e060b Compare August 19, 2026 08:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e717937cfb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coder coder deleted a comment from coderagents Bot Aug 19, 2026
@coder coder deleted a comment from coderagents Bot Aug 19, 2026
@coder coder deleted a comment from coderagents Bot Aug 19, 2026
@coder coder deleted a comment from coderagents Bot Aug 19, 2026
An enabled agent_runtime_hours feature with the limit omitted means the
license grants unlimited runtime hours (allocation claim -1). The card
previously rendered the invalid-limits error for that shape; it now
shows a full neutral bar with "Limit: Unlimited" and the tooltip
without threshold copy, mirroring SeatUsageBarCard's unlimited state.
The invalid-limits error is kept for negative limits, which can only
come from a decoding bug.
The allocation-reached tooltip now reports the floored actual usage
percentage (1,200 of 1,000 hours shows 120%) instead of always claiming
100%. The soft-limit percentage is floored rather than rounded so a
999/1,000-hour soft limit displays as 99% instead of crossing the
allocation boundary. Missing usage data no longer counts as reaching a
zero soft limit, and story tooltip assertions query the role=tooltip
node so they fail when the popover does not open.
A full green bar with no thresholds read as 100% usage. Unlimited
allocations now fill the track with purple diagonal stripes so the
full-width bar reads as an unmetered allocation instead of usage
approaching a limit.
The unlimited allocation bar keeps its diagonal stripes but switches
from purple back to the green highlight, and the right half of the
bar fades out into the track so the pattern reads as an open-ended
allocation rather than a full meter.
When a license carries a hard limit, the track scales to the
enforcement range: a solid red line marks the hard cap at the right
edge and a dotted yellow line marks the allocation, whose limit label
follows the marker. If the allocation sits close enough to the hard
cap for the labels to collide, the hard cap label moves above the
bar. Usage at or beyond the hard cap fills the track with red
diagonal stripes and the tooltip names the cap.

Threshold percentages now render with one floored decimal place
(999/1,000 hours shows 99.9% instead of 99%), still never crossing a
boundary the underlying hours have not reached.
…w total agent hours with one decimal

Derive the Total agent hours card's usage from the entitlement's new
actual_ms field, floored to tenths of an hour with integer math so the
displayed number and the reached states flip at the same instant as the
backend's whole-hour thresholds. Usage renders with exactly one decimal
(e.g. 435.8, 1,000.0); the limit and hard cap labels stay whole because
the claims are whole hours.
The fill is now colored by position instead of switching as a whole:
green until the soft limit, yellow from the soft limit to the
allocation, and red from the allocation to the hard cap. Each
threshold carries a marker line extending past the track: dotted
yellow for the soft limit, red for the allocation, and a double-width
primary-color line for the hard cap. Reaching the hard cap shows a
destructive pill above the bar stating that chat concurrency is
enforced.

New stories cover usage between the soft limit and the allocation and
between the allocation and the hard cap.
… agent hours labels inside the card

Replace the emdash fallback for missing usage data with N/A, and move
the limit label above the bar when the allocation marker sits within
the first 15% of a hard-cap scaled track, where the centered label
would spill outside the card and over the Used label.
…ect agent hours reached states

Turn the whole fill red when a metered allocation without a hard cap
is reached: the track ends at the allocation, so there is no position
past the limit where a red segment could render, and the previous
gating on a hard cap left the bar green or yellow in the reached
state. Also drop the concurrency-enforcement claim from the hard-cap
pill because no backend path enforces the hard limit yet.
Add MockAgentRuntimeHoursFeature to testHelpers/entities and spread it
in every TotalAgentHoursCard story instead of re-declaring the server
Feature shape per story, so entitlement defaults and the paired
actual/actual_ms fields stay defined in one place.
… reuse the runtime hours fixture in the view story

Spread MockAgentRuntimeHoursFeature in the TotalAgentHoursUsage view
story instead of rebuilding the entity inline, and drop the story
comment that restated the story name and its ordering assertion.
Below the md breakpoint the centered limit label collides with the
right-aligned hard cap label at interior marker positions, so it moves
above the bar instead, left-aligned in the row shared with the
hard-cap pill. Also drop the fixture comment that restated the
MockAgentRuntimeHoursFeature values.
… the bar red at a coincident hard cap

The backend accepts a hard cap equal to the allocation, which places
the shared threshold at the track's right edge where no red segment
can render past the limit. Key the full-red reached fill on the limit
boundary sitting at the track edge instead of on the absence of a hard
cap, so the coincident case reads as reached like the no-cap case.
Renders the usage period dates above the bar, matching ManagedAgentsConsumption, so admins can tell which license period the shown consumption covers. A missing or unparsable period omits the dates row; the MissingUsagePeriod story pins that fallback and the shared fixture gains a usage_period.

Also trims the narrated comments in the card and its stories down to the non-obvious invariants, per review.
… the hard cap badge and use reached wording

The shared Badge applies text-nowrap, so the full-sentence hard cap
badge overflowed narrow cards; this instance wraps instead. The badge
shows at usage equal to the hard cap (the boundary where the
concurrency cap re-engages), so it now reads "limit reached" rather
than "exceeded", which is false at equality.

Also replaces the en dash in the usage period label with a hyphen,
which broke CI at lint/emdash.
@jaaydenh
jaaydenh force-pushed the agent-hours-card-vky8 branch from ca71301 to 1e010df Compare August 19, 2026 15:09
@jaaydenh
jaaydenh merged commit e5deb57 into main Aug 20, 2026
26 checks passed
@jaaydenh
jaaydenh deleted the agent-hours-card-vky8 branch August 20, 2026 05:42
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants