Skip to content

feat(devin-connect): surface real ACU usage - #256

Open
andya1lan wants to merge 3 commits into
dwgx:masterfrom
andya1lan:fix/devin-acu-billing
Open

feat(devin-connect): surface real ACU usage#256
andya1lan wants to merge 3 commits into
dwgx:masterfrom
andya1lan:fix/devin-acu-billing

Conversation

@andya1lan

@andya1lan andya1lan commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Decode fractional ACU cost from DEVIN_CONNECT response frames.
  • Accumulate ACU independently from credit and token usage.
  • Read cycle-level ACU consumption and an optional limit from GetUserStatus.
  • Show ACU in the existing Dashboard quota area when personal quota dimensions are absent.
  • Treat an explicit 0 ACU as discovered data while keeping missing data unknown.
  • Persist only the normalized quota projection returned by GetUserStatus.

Why the existing #239 wiring is incomplete

The existing #239 implementation carries a billing object through the DEVIN_CONNECT completion path, but real ACU usage still cannot reach account totals or the Dashboard.

There are two separate gaps.

First, committed_acu_cost is encoded as a protobuf fixed-width floating-point field. The billing decoder and calibration dump handled varints and length-delimited fields, so the ACU field remained invisible even when the upstream returned it.

Second, the account accumulator only consumed credit cost. A decoded ACU value therefore had no independent storage or Dashboard consumer.

The incomplete flow was:

DEVIN_CONNECT frame
  → billing channel exists
  → fixed64 ACU field is not decoded
  → no acuCost accumulator
  → Dashboard has no real ACU value

Validation also requires an upstream account that is eligible for ACU accounting, which limits who can confirm the wire format and billing semantics.

Fix

Per-request DEVIN_CONNECT accounting

  • Decode billing scalars from varint, fixed64/double, and fixed32/float wire types.
  • Recognize the paid-verified top-level #22 fixed64 value as committed_acu_cost.
  • Preserve fractional precision through streaming and non-streaming completion paths.
  • Pass { creditCost, acuCost } separately into recordAccountSpend.
  • Persist acuCost independently under the account lifetime totals.

ACU is never added to credit cost because they are different units.

Cycle-level usage discovery

GetUserStatus is used as the primary source for the current upstream cycle:

  • PlanStatus #19acu_consumed
  • PlanStatus #20acu_limit, when available

The Dashboard projection is capability-based:

  1. Prefer GetUserStatus ACU fields.
  2. Fall back to the local DEVIN_CONNECT lifetime accumulator when cycle data is absent.
  3. Do not inspect plan, tier, account, or organization names to decide whether ACU applies.
  4. Do not infer a limit when the upstream does not return one.

Dashboard behavior

When daily, weekly, Prompt, and Flex quota dimensions are absent but ACU accounting is discovered, the existing quota area shows:

  • consumed ACU;
  • the upstream limit and progress bar when a numeric limit is returned;
  • an explicit unavailable-limit state otherwise;
  • whether the value is a GetUserStatus cycle snapshot or a local DEVIN_CONNECT lifetime total.

An explicit zero remains visible as 0 ACU. Missing accounting data remains absent rather than being rendered as zero.

Legacy -1 quota sentinels are normalized to null, preventing values such as -0.01 from appearing or being mistaken for personal quota data.

Dashboard UI design

The ACU UI is implemented within the existing Dashboard quota area. No new Dashboard page, browser dialog, or separate ACU-only panel is introduced.

The screenshot below shows the expected UI states:
Snipaste_2026-08-18_01-56-45@2x

Upstream limitations

ACU limit visibility appears to be permission-scoped upstream.

Ordinary account credentials may return acu_consumed without returning acu_limit. Organization or administrative reporting contexts may expose allocation information separately, but GetUserStatus does not guarantee that the current account can read it.

The implementation therefore shows consumed ACU when available and leaves the limit unavailable instead of inferring an organization-wide allocation.

The local fallback is lifetime-local and is not presented as a billing-cycle value.

Verification

Automated verification:

  • 400/400 focused DEVIN_CONNECT, billing, catalog, Dashboard, i18n, and accounting tests pass.
  • Fixed64 and fixed32 billing regression fixtures pass.
  • Explicit-zero ACU discovery is covered.
  • Negative legacy quota sentinel normalization is covered.
  • Normalized GetUserStatus projection behavior is covered.
  • npm run secret-scan passes.
  • git diff --check passes.

The full npm test run did not complete successfully because the upstream test/update-script-release-target.test.js remained pending for more than 270 seconds and had to be stopped. That test is unchanged by this PR and is not reported as passing.

Live verification used two accounts billed through ACU accounting:

  • one account returned a fractional acu_consumed value;
  • another account returned an explicit zero value;
  • after the upstream reporting delay, the fractional consumed value matched the value shown by the official Dashboard;
  • neither ordinary account received an ACU limit from GetUserStatus.

The agreement after the reporting delay confirms that the decoded value represents real upstream ACU consumption rather than a local estimate.

Checklist

  • Code style matches existing files.
  • No new npm dependencies.
  • LS/protobuf field sources are documented: response top-level #22, PlanStatus #19/#20.
  • Dashboard changes add no native browser dialogs.
  • Missing upstream data remains unknown rather than being guessed.
  • Feature issue linked.

Closes #239.

Copilot AI lite review requested due to automatic review settings August 17, 2026 17:54

Copilot AI 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.

Pull request overview

This PR extends DEVIN_CONNECT and GetUserStatus accounting to surface real ACU usage end-to-end: decode fractional ACU from protobuf frames, persist it independently from credit cost, and expose it in the Dashboard quota UI when personal quota dimensions are absent.

Changes:

  • Added protobuf numeric decoding support for billing fields across varint + fixed64/double + fixed32/float, including paid-verified top-level #22committed_acu_cost.
  • Introduced a separate per-account lifetime acuCost accumulator and wired connect billing { creditCost, acuCost } into recordAccountSpend.
  • Normalized/GetUserStatus ACU fields (acuConsumed, optional acuLimit) and updated Dashboard/i18n to display ACU quota when applicable.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/strict-usage-total.test.js Extends monotonic/poisoning tests to include acuCost in total spend counters.
test/devin-connect.test.js Adds fixture + assertions for decoding top-level #22 fixed64/double committed ACU cost and updates default billing tag expectations.
test/devin-connect-openai.test.js Verifies fractional ACU billing is preserved through both non-stream and SSE streaming completion paths (without exposing it in SSE chunks).
test/devin-connect-finish-callsite.test.js Adds call-site guard ensuring finish events preserve paid ACU billing through the default billing map.
test/devin-connect-calibrate.test.js Adds tests for persisted token lookup and new calibration classification behavior (including ACU tag #22 handling).
test/dashboard-syntax.test.js Asserts Dashboard HTML/i18n wiring for ACU quota/spend rendering and raw-payload scrubbing.
test/connect-rate-table-wiring.test.js Verifies connect billing maps credit vs ACU into separate spend units and accrues ACU independently.
test/billing-userstatus-decode.test.js Adds fixed64/double helpers and verifies PlanStatus #19/#20 decode into acuConsumed/acuLimit.
test/auth-total-spend.test.js Ensures acuCost is included in public totalSpend shape and survives serialize/load.
test/acu-discovery.test.js New tests for ACU capability discovery (prefer upstream snapshot, preserve explicit zero, fallback to local billing, sentinel normalization).
src/windsurf-api.js Normalizes ACU fields from GetUserStatus and treats negative legacy quota sentinels as absent.
src/handlers/chat.js Switches connect spend attribution from credit-only to {creditCost, acuCost} via connectBillingSpend; exports it for tests.
src/devin-connect.js Adds numeric scalar decoding across varint/fixed64/fixed32 for billing fields; enhances structured dump output for fixed-width fields; defaults billing tags include committed_acu_cost=^22.
src/devin-connect-catalog.js Adds numericField helper and decodes PlanStatus ACU consumed/limit (19/20) from protobuf UserStatus.
src/dashboard/index.html Renders ACU quota in the quota column/detail when personal quota dimensions are absent; shows separate lifetime ACU spend when relevant.
src/dashboard/i18n/zh-CN.json Adds ACU-related quota/spend strings (Chinese).
src/dashboard/i18n/en.json Adds ACU-related quota/spend strings (English).
src/dashboard/api.js Scrubs any raw payload defensively from refresh-credits responses.
src/auth.js Persists acuCost in _totalSpend, records ACU spend, derives acuUsage projection for Dashboard, and stops returning/persisting raw userstatus in refreshCredits output.
scripts/devin-connect-calibrate.mjs Improves calibration classification (ACU #22, provider #21, actual model at #7.9), and resolves token from configured/persisted accounts.json path.
docs/DEVIN-CONNECT-CUTOVER.md Updates documentation to reflect paid-verified committed ACU mapping and expanded dump semantics.
.env.example Updates env docs for billing/cache decoding defaults and top-level ^N tag support.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/auth.js Outdated
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.

[Feature] 支持 获取真实的ACUs 计费

2 participants