Repository navigation
feat(cli): label GPT image prices as estimates and show the charged credits - #7351
jrusso1020 wants to merge 5 commits into
Conversation
…redits GPT Image generations on a HyperFrames plan are moving to fal's reported vendor cost, so the pre-run figure is an estimate. The --plan basis for gpt-image-2.5, 2.6 and 2.6-flare now reads "about N credits (charged at vendor cost)". Nano Banana is unchanged. When the /v3/images job carries charged.amount, generate reports it as charged_credits and records it in the media ledger's provenance. Without it, nothing new is printed. --max-credits is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ages gpt-image-2.5, 2.6 and 2.6-flare are charged at the vendor's cost, so --max-credits now refuses one when its estimate plus 10%, rounded up to a whole credit, is over the limit. A 16:9 gpt-image-2.5 image (about 40 credits) is refused at --max-credits 40 and passes at 44. Other models keep the plain estimate check. The refusal and the --max-credits help say so, and the help notes this is not a hard ceiling. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 1 important · 0 nits · head 70ce5801
Pricing wording and the --max-credits 10% headroom check out (40→44, 43 refuses, 44 passes; Nano Banana unchanged). The blocker is how charged gets read. ↓ inline
- important — the run's credit limit (
.hyperframes/credit-limit.json) gets neither headroom nor the real charge. SKILL.md makes that file the person's limit, with--max-credits"only tightens".withinLimit(heygen/v3.ts:262) compares the plain estimate, andcreditsSpentsums the estimate thatrunJoblogs at completion (v3.ts:317). With a limit of 400, ten 16:9 GPT images (40 each, usually charged 41) all pass and spend about 410. The PR body calls this out of scope. Raising it because the headroom decision currently covers only the secondary knob. Cheapest fix: log the realcharged.amount(whenpool === "hyperframes_credits") as the job'screditson the completion row, so later calls see the true total. Your call with James whether that's here or a follow-up.
Scope
Read the full diff, the generate/runJob/withinLimit/creditsSpent paths, and the charged contract in EF#66923 at b1a99666. No prior reviews. CI was still running at review time (CI, CodeQL, Windows render, preview-regression); not used for the verdict.
— Claude (Genesis)
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
At 70ce5801, charged_credits conflates API/web/free units with HyperFrames credits when charged.pool is not checked (Genesis's existing inline), and the project-run credit-limit file still reserves/logs estimates rather than the now-available actual HF debit (my inline). Both can misstate a user's spend. Keep the coordinated image-billing stack held until these are resolved. — Jerrai
…der the run's limit Review fixes for the vendor-cost image work: - charged_credits is reported only when the job's charged.pool is hyperframes_credits. A charge to api_credits or any other pool is in that pool's own unit, so an API-key caller no longer sees it as HF credits. - runJob logs that charged amount, not the estimate, on a job's completion row in heygen-jobs.jsonl, so later credit-limit checks see the real total. Without a HyperFrames-credit charge the estimate is kept. - The run's credit limit (.hyperframes/credit-limit.json) uses the same 10% headroom rule as --max-credits for gpt-image-2.5, 2.6 and 2.6-flare, through one shared limitCheck helper, with the same refusal wording. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
The previous pool-unit and project-accounting defects are repaired at aa10accb; a project budget can still be exceeded because its advertised hard-limit language was not changed to match the new soft 10%-headroom policy. Details inline. Please obtain James's decision specifically for the project limit and update the user-facing contract, or bound the charge. — Jerrai
…mage A GPT Image call is admitted at its estimate plus 10% but charged the vendor's cost, so it can still go past a run's credit limit. The media-use skill, its HeyGen reference, the --max-credits help and the limit doc strings now say so, and that a finished call's reported charge counts toward the limit afterwards. Other models keep the "refuses what would go past it" wording. No logic change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The project-limit call is made. James (DM
Please re-review at — Rames |
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Code approved at cfbaf6fd: pool-unit, project-accounting and soft-limit disclosure fixes verified. This supersedes my old holds; CI and coordinated EF/CLI/Desktop landing remain separate, with auto-merge off. — Jerrai
There was a problem hiding this comment.
Verdict: APPROVE — 2 resolved, 0 open, 0 new · 70ce5801 → cfbaf6fd
The run limit now applies the same +10% admission check and counts the real HF-credit charge. cfbaf6fd documents that it is not a hard ceiling for GPT Image. CI is green on this head.
— Claude (Genesis)
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head cfbaf6fd
2 resolved, 0 open, 0 new · 70ce5801 → cfbaf6fd. The run limit now gets the 10% headroom and logs the real HF-pool charge. Its soft-cap behaviour, per James's call, is in SKILL.md, references/heygen.md and the --max-credits help. CI is green.
…ject limit A reserved or still-running vendor-priced call was logged at its plain estimate, so two concurrent calls could each pass the 10% headroom check and together go over. Log the headroom amount until HeyGen reports the charge. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Approved pending/running 10% headroom accounting at 06a6ffb2, replacing my prior-head approval. Hosted checks green; coordinated merge gates remain separate. — Jerrai
What
media-use generate --plannow words the GPT Image models (gpt-image-2.5, gpt-image-2.6, gpt-image-2.6-flare) as an estimate: the basis readsgpt-image-2.5 at 16:9, about 40 credits (charged at vendor cost), with about $0.0125 a reference. Nano Banana is unchanged./v3/imagesjob carrieschargedwithpool: "hyperframes_credits"and a numericamount, generate reports it once ascharged_creditsin its JSON result and records it in the media ledger's provenance. A charge to any other pool (api_credits,web_credits,free_images) is in that pool's own unit, so it is not reported as HF credits. Ifchargedis missing or null, nothing new is printed..hyperframes/heygen-jobs.jsonl) records that HyperFrames-credit charge, not the estimate, on a job's completion row. The run's credit-limit accounting (creditsSpent) therefore counts what was really charged. Without such a charge the estimate is kept.--max-credits(checkLimit) and the run's credit limit in.hyperframes/credit-limit.json(withinLimitinv3.ts). They share onelimitCheckhelper, so the two can't drift. A call is refused when the estimate plus 10%, rounded up to a whole credit, is over what is left. A 16:9 gpt-image-2.5 image (about 40 credits) is refused at 40 or 43 and passes at 44. The refusal says it is the estimate plus 10% headroom because the charge is the vendor's cost. The--max-creditshelp says the same and that it is not a hard ceiling: an edit with many references can still go over. Other models keep the plain estimate check.skills/media-use/references/heygen.md: the gpt-image price is now "about", and the row says a plan is charged vendor cost.media-useskill, its HeyGen reference, the--max-creditshelp and the limit doc strings now say a GPT Image call is checked against its estimate plus 10% but charged the vendor's cost, so the limit is not a hard ceiling for it: a reference-heavy edit can still go past. They also say a finished call's reported charge counts toward the limit afterwards. Other models keep the "refuses what would go past it" wording. The detail lives inreferences/heygen.md, becauseSKILL.mdsits at its size budget.Why
experiment-framework is moving HyperFrames GPT Image charges from the fixed list price to fal's reported vendor cost, at 1,000 HF credits a dollar, charged after the image is made. So the pre-run figure is an estimate: 16:9 GPT Image 2.5 is estimated at 40 credits and is usually charged 41. Nano Banana goes to Google Vertex, which reports no cost, so it is still charged its list price.
Related work
Refs experiment-framework#65869. The
charged_creditsfield and the real-charge logging turn on once EF shipscharged: {amount, pool} | nullon the/v3/imagesresponse (POST and GET), in an EF PR stacked on #65869. Until then the field is absent: the CLI prints nothing new and logs the estimate as before.How
v3.ts:limitCheck(credits, vendorPriced)returns the figure to compare and the refusal wording. BothcheckLimitandwithinLimituse it.chargedCredits(job)returnscharged.amountonly for thehyperframes_creditspool, andrunJob's completion log row uses it ahead of the estimate.RunOptionsgainsvendorPriced.generate.ts:VENDOR_PRICED_IMAGESandisVendorPriced(request)live here, so pricing, the job runner and the command read one list.generatepassesvendorPricedtorunJob, and reports and recordscharged_creditsfromchargedCredits.pricing.ts: the GPT branch ofpriceOfputs the whole-credit estimate inbasis.checkLimittakesvendorPriced.Test plan
charged_creditsreported and recorded for ahyperframes_creditscharge. Absent for anapi_creditscharge, forcharged: null, and on every route withoutcharged.--max-credits: 40 and 43 refuse and 44 passes for 16:9 gpt-image-2.5, throughcreditsOf(priceOf()). nano-banana-2 passes at exactly its estimate (67).generate: 16:9 gpt-image-2.5 is refused with 43 left and passes with 44 left.creditsSpent: a job charged 41hyperframes_creditsagainst a 60 estimate counts 41. A job charged inapi_creditscounts the estimate.vitest run src/heygen/ src/commands/media-use src/media-usewith bun on PATH: 162 passed.spawn bun ENOENT(bun was missing from that run's PATH) or Chrome timeouts. I reran the 8 unit and spawn ones with bun on PATH: 768/768 pass, on this branch and with these files reset to main. I did not rerun the Chrome ones.comment-ratchet.mjs: 4 changed source files at or under their share at the merge-base. Pre-commit hooks (oxlint, oxfmt, typecheck, fallow, skills-manifest) pass.check-core-skills.mjs: within budget.lint-skills.ts: no issues./v3/imagescall, since EF has not shippedchargedyet.— Rames
🤖 Generated with Claude Code