mirror of
https://github.com/Comfy-Org/comfy-typescript-sdk.git
synced 2026-11-04 23:47:27 +00:00
[PR #210] feat(models): expose the queued-submit cost estimate as RequestHandle.estimate #210
Labels
No labels
audit:ai-readiness
audit:community
audit:github
audit:health-scoring
audit:policy
audit:release
audit:supply-chain
bug
cursor-review-pin
effort:medium
effort:small
effort:trivial
priority:nice-to-have
priority:recommended
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-typescript-sdk#210
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-typescript-sdk/pull/210
Author: @mattmillerai
Created: 10/9/2026
Status: 🔄 Open
Base:
main← Head:be-19976-request-handle-estimate📝 Commits (2)
35c2461feat(models): expose the queued-submit cost estimate as RequestHandle.estimate7630bb8fix(models): reject a quote missing its figure or with a non-numeric dollar string📊 Changes
6 files changed (+454 additions, -4 deletions)
View changed files
📝
CHANGELOG.md(+12 -0)📝
README.md(+10 -0)📝
src/sdk/index.ts(+1 -0)📝
src/sdk/modelRequests.test.ts(+206 -2)📝
src/sdk/modelRequests.ts(+221 -2)📝
src/sdk/models.ts(+4 -0)📄 Description
ELI-5
When you queue a model request, Router can send back a price quote with the acceptance. Until now the SDK threw that quote away. Now it is on the handle you get back, as
handle.estimate. It isnullwhen there is no quote, andnullnever means "free".What changed
CostEstimate(exported type):sourceis the server's open string, andisExact/isEstimated/isUnknownare the booleans to branch on. A source this release does not recognise reads as unknown, which is what the contract asks for. It also carriescurrency,provider,modelandpricingAsOf. The dollar figuresamount/minAmount/maxAmountare decimal strings, so nothing gets rounded.amountCents/minAmountCents/maxAmountCents/creditsare numbers, andreasonandraware included too. An optional field the server leaves out reads asnull, following the repo'sQueueUpdatestyle.costEstimateOf(value)insrc/sdk/modelRequests.tsis a lenient reader that never throws. Any malformed shape givesnull: not an object, a required field missing or empty, an optional field present with the wrong type or a non-finite number, a dollar figure that is not a plain decimal numeral, anexactquote with noamount, or anestimatedquote missing a bound.sourceis compared verbatim (not trimmed), andrawis a frozen shallow copy of the wire object. A malformed quote never fails a submit the server has already accepted.RequestHandle.estimate: CostEstimate | nullis set from the submit body inmodels.submit.subscribebuilds its handle internally and does not expose it. It isnullon a handle rebuilt bycomfy.models.handle, andnullon an idempotent replay: ifIdempotent-Replayedis present the estimate is forced tonulleven when the body carries one, because the server does not store the original quote.queueScriptgets anestimateknob (left out by default) andsubmitHeaders. Tests cover exact, estimated, unknown, unrecognised and untrimmed source, absent, 24 malformed shapes (including missing figures and non-numeric dollar strings), non-finite numbers, the frozenrawcopy, replay and a rebuilt handle.Unreleased › Addedentry, and a TSDoc note onModels.submit.Judgment calls
null. Dropping only that field would leave a partial quote, e.g.isExactwithamount: null, which a caller could misread as zero. The contract says an absent amount must never be read as free.exactquote with noamount, or anestimatedquote missing a bound, reads asnull. The contract saysexactcarriesamountandestimatedcarries both bounds. Returning one without them would give a callerisExactwithamount: null, the misread-as-zero case this reader exists to prevent. (Changed after review; the first version checked each field on its own.)reasonstays verbatim. The contract reads anyreasonother thannot_quotable/unpriced_modelasnot_quotable. The TSDoc says so and suggests branching onunpriced_model, rather than adding a derived flag the Python twin doesn't have.costEstimateOfis not re-exported from the package root. Only theCostEstimatetype is. The reader is reachable from the module for tests and can be promoted if amodels.estimate()method lands.Provenance
pnpm test), including theRequestHandle.estimatecasespnpm lint,pnpm format:check,pnpm typecheck);pnpm check:spec-driftOK;pnpm buildOKIdempotent-Replayed: true, so dropping the guard would fail itsdk-parityis red on this PR and onmain, and the cause is not in this PR: the Python SDK addedQueueBacklogFull, which makes the snapshot stale. #209 refreshes the snapshot and retires that leadResidual
CostEstimate). No such Python PR existed when this was written. A search of open and closed Python SDK PRs for "estimate" found only spec syncs. Two follow-ups: (1) land the Python twin (CostEstimatewithis_exact/is_estimated/is_unknown, andRequestHandle.estimate), and (2) decide whetherscripts/python-surface.mjs/src/sdk/surface-parity.test.tsshould start diffing data-type names likeCostEstimate. Today they compare onlymodelsmethods and error classes, so a name mismatch here would not fail any check.maindoes not declareestimateon the submit yet.RouterQueueSubmitFields.estimatecomes in with the still-open Router spec sync PR (#209).RouterCostEstimateitself is already onmain, and this change reads the field the way #209 declares it. Nothing is generated from the Router spec, and no contract test pins this field, so the two PRs can merge in either order. After #209 lands, someone could add a contract assertion thatRouterQueueSubmitFieldsdeclaresestimate→RouterCostEstimate.reasonvaluesbyokandpricing_unavailablecome in with #209. They are passed through as the server's open string. The docs list onlynot_quotable/unpriced_model, the valuesmain's spec documents today.Summary by CodeRabbit
New Features
CostEstimatetype is also available for use in TypeScript.null; this does not indicate that a request is free.Documentation
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.