Commit 22c9b42
feat(fal): surface billed cost as result.usage.unitsBilled (#723)
* feat(fal): surface billed cost as result.usage.unitsBilled
The fal adapters discarded fal's response headers, so the actual billed
cost of a generation was unrecoverable through the SDK. fal returns the
real billed quantity in the `x-fal-billable-units` header on the result
fetch; this surfaces it as `result.usage.unitsBilled` so consumers can
compute exact media-generation cost without wrapping `fetch` themselves.
- `TokenUsage` gains an optional `unitsBilled` (a bare count of priced
units, sibling to `durationSeconds`; the unit name itself is provider
-defined and looked up via the pricing API, not carried here).
- A `config.fetch` wrapper reads `x-fal-billable-units` off every fal
response, keyed by `x-fal-request-id` (the same value the client
surfaces as `Result.requestId`), so the adapter's lookup always
matches the fetch the units came from. `config.fetch` is used rather
than `responseHandler` because the queue ops clobber a global handler.
- All five fal media adapters (image, audio, video, speech,
transcription) populate `result.usage.unitsBilled` when fal reports it.
- `VideoUrlResult` gains a `usage` slot; `getVideoJobStatus` now emits
the `video:usage` event and returns `usage` on completion.
Closes #722
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
* feat(examples): show fal unitsBilled in ts-react-media
Surface the new `result.usage.unitsBilled` in the media example so the
billed quantity is visible after a generation — a caption under each
generated image/video ("Billed N fal units"). Verified against the live
fal API: a fal-ai/flux/schnell generation reports unitsBilled: 1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(examples): use a runtime-valid size for grok-imagine-image
fal's generated `size`/`resolution` type for `xai/grok-imagine-image`
offers `16:9_1K` / `16:9_4K`, but the live API rejects those resolutions
("Input should be '1k' or '2k'") — the vendor enum is out of sync with
the API. `'16:9_4K'` therefore type-checked but 422'd at runtime. Pass
`aspect_ratio: '16:9'` via modelOptions instead and let the endpoint
default the resolution; verified against the live fal API.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(fal): inject fetch instead of overriding the global
Address CodeRabbit + review feedback: dependency-inject the underlying
fetch rather than mutating globals.
- `createBillingFetch(baseFetch = globalThis.fetch)` now takes the fetch to
delegate to, and `FalClientConfig` gains an optional `fetch` override that
`configureFalClient` wraps for usage capture.
- The E2E route passes a per-request redirecting `fetch` via
`falImage(model, { fetch })` instead of swapping `globalThis.fetch` —
removing the concurrency race CodeRabbit flagged (no global mutation, no
try/finally restore).
- `billing.test.ts` injects a fake fetch directly instead of
`vi.stubGlobal('fetch')`.
- Changeset: reword "billed cost" → "billed units" to match the surfaced
`usage.unitsBilled` field.
Verified: full `pnpm test:pr` green, fal E2E spec green, and a live
fal-ai/flux/schnell call still reports unitsBilled via the default
(no-override) path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>1 parent afb2960 commit 22c9b42
33 files changed
Lines changed: 852 additions & 29 deletions
File tree
- .changeset
- docs
- media
- examples/ts-react-media/src
- components
- lib
- packages
- ai-event-client/src
- ai-fal
- src
- adapters
- utils
- tests
- ai
- skills/ai-core/media-generation
- src
- activities/generateVideo
- testing/e2e
- src
- routes
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
242 | 242 | | |
243 | 243 | | |
244 | 244 | | |
245 | | - | |
| 245 | + | |
| 246 | + | |
246 | 247 | | |
247 | 248 | | |
248 | 249 | | |
249 | 250 | | |
250 | | - | |
| 251 | + | |
| 252 | + | |
251 | 253 | | |
252 | 254 | | |
253 | 255 | | |
254 | 256 | | |
255 | | - | |
| 257 | + | |
| 258 | + | |
256 | 259 | | |
257 | 260 | | |
258 | 261 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
121 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
122 | 125 | | |
123 | 126 | | |
124 | 127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
206 | | - | |
| 206 | + | |
| 207 | + | |
207 | 208 | | |
208 | 209 | | |
209 | 210 | | |
| |||
214 | 215 | | |
215 | 216 | | |
216 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
217 | 237 | | |
218 | 238 | | |
219 | 239 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
408 | 408 | | |
409 | 409 | | |
410 | 410 | | |
411 | | - | |
| 411 | + | |
412 | 412 | | |
413 | 413 | | |
414 | 414 | | |
| |||
437 | 437 | | |
438 | 438 | | |
439 | 439 | | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
440 | 443 | | |
441 | 444 | | |
442 | 445 | | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
443 | 454 | | |
444 | 455 | | |
445 | 456 | | |
| |||
Lines changed: 18 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
209 | 209 | | |
210 | 210 | | |
211 | 211 | | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
219 | 230 | | |
220 | 231 | | |
221 | 232 | | |
| |||
Lines changed: 24 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
98 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
99 | 103 | | |
100 | 104 | | |
101 | 105 | | |
| |||
387 | 391 | | |
388 | 392 | | |
389 | 393 | | |
390 | | - | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
399 | 412 | | |
400 | 413 | | |
401 | 414 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
32 | 38 | | |
33 | 39 | | |
34 | 40 | | |
35 | 41 | | |
36 | | - | |
| 42 | + | |
37 | 43 | | |
38 | 44 | | |
39 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
223 | 223 | | |
224 | 224 | | |
225 | 225 | | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
226 | 238 | | |
227 | 239 | | |
228 | 240 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| |||
133 | 135 | | |
134 | 136 | | |
135 | 137 | | |
| 138 | + | |
| 139 | + | |
136 | 140 | | |
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
140 | 144 | | |
141 | 145 | | |
142 | 146 | | |
| 147 | + | |
143 | 148 | | |
144 | 149 | | |
145 | 150 | | |
| |||
0 commit comments