Skip to content

feat: emit x-fal-request-id and opt-in x-fal-billable-units on fal queue responses#270

Open
tombeckenham wants to merge 2 commits into
CopilotKit:mainfrom
tombeckenham:269-fal-queue-responses-omit-x-fal-request-id-x-fal-billable-units-so-tanstack-ai-fal-can-t-surface-unitsbilled-on-replay
Open

feat: emit x-fal-request-id and opt-in x-fal-billable-units on fal queue responses#270
tombeckenham wants to merge 2 commits into
CopilotKit:mainfrom
tombeckenham:269-fal-queue-responses-omit-x-fal-request-id-x-fal-billable-units-so-tanstack-ai-fal-can-t-surface-unitsbilled-on-replay

Conversation

@tombeckenham

Copy link
Copy Markdown
Contributor

Closes #269.

Problem

aimock's fal dispatcher served queue-status / queue-result responses without x-fal-request-id or x-fal-billable-units. @tanstack/ai-fal (≥ 0.8.x) installs a config.fetch wrapper that reads both headers off every fal response and bails without the request-id, so result.usage.unitsBilled always came back undefined on replay — no way to author a fixture that exercises a consumer's cost/billing path.

Changes

  • x-fal-request-id is now always emitted on queue-status and queue-result responses (including the 202 in-progress result), matching real fal.
  • x-fal-billable-units rides the completed (200) queue-result when a fixture opts into a billed quantity via billableUnits — available on the onFalQueue / onFalRun / onFalImage / onFalVideo builders ({ billableUnits }) and as response.billableUnits in JSON fixtures.
  • Record mode captures the upstream x-fal-billable-units header during the queue walk (walkFalQueue now returns { body, billableUnits }) and persists it into response.billableUnits, so recorded fixtures round-trip billing with no hand-editing. The legacy fal-audio walk takes the body only.

Tests

  • request-id present on status/result (and no billable header by default)
  • billable header on the completed result only; withheld on the 202 until completion
  • record-mode capture: stub upstream sets the header → asserts same-session replay header and persisted response.billableUnits

Full suite green; tsc / eslint / prettier clean. CHANGELOG and the fal-ai docs page updated.

…eue responses

fal queue status/result responses now always set x-fal-request-id, matching
real fal — adapters like @tanstack/ai-fal key their billing lookup off it and
previously bailed without it. A billableUnits fixture field (onFalQueue /
onFalImage / onFalVideo opts, or response.billableUnits in a JSON fixture)
emits x-fal-billable-units on the completed queue-result so consumers can
assert their cost path and surface usage.unitsBilled on replay.

Record mode captures the upstream x-fal-billable-units header during the queue
walk and persists it into response.billableUnits, so recorded fixtures
round-trip billing with no hand-editing.
@pkg-pr-new

pkg-pr-new Bot commented Jun 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@copilotkit/aimock@270

commit: 95a8da4

… comments

Address PR review:
- correct comments that overstated x-fal-request-id as emitted on "every"
  queue response (it rides status + result only, not submit/cancel/404)
- soften the @tanstack/ai-fal version pin in the RawJSONResponse doc
- add a billableUnits: 0 test pinning the != null / Number.isFinite guard so a
  truthy-check regression that drops the zero-cost header can't pass green
- add record-mode tests asserting an absent or non-numeric upstream
  x-fal-billable-units leaves the persisted fixture (and replay) header-less
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.

fal queue responses omit x-fal-request-id / x-fal-billable-units, so @tanstack/ai-fal can't surface unitsBilled on replay

1 participant