Repository navigation
feat(usage): Client.usage for metered usage and usage gates - #283
Conversation
Adds Client.usage.summary, listRecords, iterateRecords and listGates over /platform/usage, /platform/usage/records and /platform/gates, the usage.recorded webhook payload, and the bansafe.risk_changed and bansafe.health_changed payloads the re-pinned contract publishes. Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Review limit reached
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Next included review available in 17 minutes. View limit detailsLimit details: You’ve used the included review currently available. Your 80 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. The included review limit has been reached and this organization has disabled usage-based review continuation. Wait for reviews to reset or ask a billing admin to change After included review limits. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (15)
Comment |
Co-Authored-By: Claude <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 96208fd436
ℹ️ 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".
| readonly meter: string; | ||
| readonly quantity: number; | ||
| readonly unit: string; |
There was a problem hiding this comment.
Use the closed meter and unit types in webhook payloads
For consumers constructing or exhaustively handling usage.recorded, these string annotations accept values that the pinned webhook contract rejects: both fields are closed enums, already represented by the exported UsageMeter and UsageUnit types. Using those types here prevents invalid payloads such as meter: "unknown" from compiling and preserves exhaustive handling.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in be1b75d: UsageRecordedPayload now uses UsageMeter, UsageUnit, UsageKeySource, UsageSourceKind and UsagePricingState, and a type test asserts it equals UsageRecord.
| /** One contributing factor behind a risk level. */ | ||
| export interface BanSafeRiskFactor { | ||
| readonly key: string; | ||
| readonly group: string; |
There was a problem hiding this comment.
Preserve the closed BanSafe factor-group enum
When consumers branch on risk-factor groups, typing group as an arbitrary string loses the contract's closed 16-value enum and allows unsupported group names to compile. Define the corresponding string-literal union here so bansafe.risk_changed remains as strongly typed as its other enum fields.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not changed on this branch. sdks dev is getting a named BanSafeRiskFactorGroup union through sdks#282; the coordinator's dev merge into this branch resolves it, so this PR leaves the BanSafe block untouched to avoid a conflicting definition.
| * Gate state covers the whole team, so this needs an organization client; | ||
| * the API refuses project credentials with 403. |
There was a problem hiding this comment.
Document project-token access to usage gates correctly
For project-token users, this states the opposite of the pinned /platform/gates contract, whose operation description explicitly allows project tokens to access their own project; the implementation also exposes listGates on project clients and injects their bound projectId. Claiming that the API returns 403 can cause users to avoid a supported operation, so describe it as project-scoped instead.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Keeping the wording. The pinned snapshot in contracts/ predates the change; the current API contract (#228, openapi.management.json) says "Requires a team API key with sessions:read. Project tokens are not accepted." and the handler rejects project credentials with 403 (if (ctx.projectId) throw errForbidden("usage gates require a team credential") in routes/console/usage-handlers.ts). The snapshot refresh comes with the contract pin update, not this PR.
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@codex review |
…-month records The usage.recorded payload now reuses UsageMeter, UsageUnit, UsageKeySource, UsageSourceKind and UsagePricingState, matching UsageRecord. listRecords documents that omitting period lists records from every month. Co-Authored-By: Claude <noreply@anthropic.com>
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Resolve duplicate BanSafe exports and fixtures while retaining the closed usage webhook enums. Refresh both contract snapshots to pending API PR #228 commit 651c137, with an explicit final dev repin requirement and SDK #282 dependency. Node 20 and 22 typechecks pass; all workspace builds, format, lint, coverage, package checks and production audit pass. Full suites have 1068 passing tests and the two known SDK #282 contract failures, which remain unchanged until that dependency merges.
…gates # Conflicts: # README.md # contracts/README.md # contracts/coverage.json # contracts/openapi.platform.json # contracts/source.json # packages/typescript/src/client.ts # packages/typescript/test/coverage-reconciliation.test.ts # packages/typescript/test/coverage.test.ts
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4fcf13acb
ℹ️ 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".
| yield* page.data.records; | ||
| cursor = page.data.nextCursor ?? undefined; | ||
| } while (cursor); |
There was a problem hiding this comment.
Reject repeated record cursors before yielding the page
When the API or a cache returns a stale page whose nextCursor was already requested, iterateRecords() requests that cursor forever and repeatedly yields the same usage records, which can duplicate downstream aggregation and generate unbounded traffic. Track requested cursors and reject a repeated cursor before yielding the replayed page, as the existing Calls export iterator does.
Useful? React with 👍 / 👎.
| value: process.env.POLYMORFA_MESSAGING_API_KEY!, | ||
| }, | ||
| apiVersion: "2026-03-20", | ||
| apiVersion: "1.0.0", |
There was a problem hiding this comment.
Use a supported contract date in the example
When users copy this quick-start example, the transport sends 1.0.0 verbatim in Polymorfa-Version, but this option expects a supported date-form contract version such as 2026-03-20—the format still used in packages/typescript/README.md. The example therefore causes otherwise valid Messaging requests to select an unsupported API version.
Useful? React with 👍 / 👎.
| protocol. Its `pmfa_ls_` credential cannot be used by `Client`, | ||
| `MessagingClient`, or their raw request helpers. Browser client tokens cannot | ||
| use the server event stream. | ||
| The SDK has no listener, event stream, `AsyncIterable`, or forwarding API. |
There was a problem hiding this comment.
Restore the documented server event stream
This statement is false for the reviewed SDK: Client.events.stream() returns an AsyncIterable, Client.events.liveSource() is also present, and the pinned contract still includes the stream and acknowledgement routes. Users relying on the root guide are incorrectly told that a supported API does not exist, contradicting the package-level streaming guide.
Useful? React with 👍 / 👎.
|
Current head 1eea217: fixed the valid repeated-cursor, Messaging version example, and server event-stream documentation findings. The gate project-token suggestion does not match merged API #228: its authoritative management OpenAPI requires a team key, and usage-handlers.ts rejects ctx.projectId with 403. Focused usage tests, typecheck, lint, format, and the full 1,151-test rerun pass (one unrelated media abort cleanup race failed on the first run). The pre-existing packageManager worktree edit remains uncommitted. @codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
Merge gate for exact head 1eea217: current-head Node 20 and 22 CI passed, and GitHub Codex completed a clean current-head review. The valid preceding review findings were fixed and the project-token gate suggestion was checked against merged API #228 and found incorrect. Local focused usage tests, typecheck, lint, format, and the full 1,151-test rerun passed; the pre-existing unrelated packageManager edit was excluded from the PR. CodeRabbit did not deliver a clean review. The owner explicitly authorized merging #283 with CI + Codex and recording that exception. Calls remains unreleased; this SDK merge does not deploy or enable it. |
Adds typed usage and gate reads to the TypeScript SDK for the accepted call-metering contract in monorepo #228, merged on
devatfdaff9a86220e3ef1f8ad75cc838dbfd03ede4eb.Client.usage.summary,listRecords,iterateRecords, andlistGatescoverGET /platform/usage,/platform/usage/records, and/platform/gates. Project clients stay bound to their own project.listGatesstill receives the API’s refusal for project credentials because gate state is team-wide. The SDK also exposes theusage.recordedwebhook payload and preservesunpricedusage semantics; this change does not charge usage or enable hard limits.The Messaging and Platform contract snapshots are byte-identical to merged monorepo
devatfdaff9a8, with no pending overlay. This branch normally merges SDKdevad5e5620003514deec3a456a99bb827b7406bc32(including analytics #281). Reconciled coverage is 459 operations: 348 covered, 111 excluded, zero missing or changed. The pre-existing localpackage.jsonpackageManager edit was preserved and is not part of this PR.The full repository verification sequence passed under both Node 20 and Node 22: clean install, format, lint, typecheck, workspace builds, tests, coverage, name checks, package dry run, and production audit. One existing media abort cleanup test failed on the first Node 20 run, then passed in isolation and in a complete clean-install rerun. No live API, npm publication, or deployed environment was exercised by these local checks; fresh current-head CI and reviews are required before merge.