12 KiB
ADDED Requirements
Requirement: Image multiplier mode
The system SHALL calculate image generation cost with group image prices and a selectable image multiplier mode. By default image billing SHALL share the existing effective group multiplier; when image_rate_independent=true, image billing SHALL use image_rate_multiplier.
Scenario: Default image billing shares current effective group multiplier
- WHEN a group has
rate_multiplier=0.15 - AND
image_rate_independent=false - AND
image_price_1k=0.2 - AND a successful image request produces one
1Kimage - THEN
actual_costis0.03 - AND the calculation matches current default behavior
Scenario: User-specific token multiplier still applies in shared mode
- WHEN a user has a user-group token multiplier override of
0.2 - AND the group has
image_rate_independent=false - AND
image_price_1k=0.5 - AND a successful image request produces one
1Kimage - THEN
actual_costis0.1 - AND the applied image multiplier is the same effective multiplier used by token billing
Scenario: Independent image multiplier allows direct final price
- WHEN a group has
rate_multiplier=0.15 - AND
image_rate_independent=true - AND
image_rate_multiplier=1 - AND
image_price_1k=0.2 - AND a successful image request produces one
1Kimage - THEN
actual_costis0.2 - AND ordinary
rate_multiplier=0.15is not applied to the image cost
Scenario: Independent image multiplier supports image discounts
- WHEN a group has
image_rate_independent=true - AND
image_rate_multiplier=0.5 - AND
image_price_1k=0.2 - AND a successful image request produces two
1Kimages - THEN
total_costis0.4 - AND
actual_costis0.2
Scenario: Migration preserves existing image price behavior
- WHEN an existing group has
rate_multiplier=0.15andimage_price_1k=1.3333333333 - AND the migration is applied
- THEN the stored
image_price_1kremains1.3333333333 - AND the stored
image_rate_independentisfalse - AND the stored
image_rate_multiplieris1 - AND default-mode image billing still produces the historical final price within decimal precision
Scenario: Omitted update fields preserve existing multiplier mode
- WHEN an admin updates a group without sending
image_rate_independent - AND without sending
image_rate_multiplier - THEN the stored image multiplier mode and image multiplier value remain unchanged
Scenario: Image multiplier can be zero only by explicit independent mode configuration
- WHEN a group has
image_rate_independent=true - AND
image_rate_multiplier=0 - AND a successful image request produces one image
- THEN the image request is free
- AND this free-image behavior does not occur unless the group explicitly enables independent image multiplier mode with zero multiplier
Requirement: Responses image output accounting
The system SHALL count generated image outputs from OpenAI Responses stream, non-stream, and passthrough paths and SHALL return the count in OpenAIForwardResult.ImageCount.
Scenario: Non-stream Responses image tool output is counted
- WHEN a non-stream
/v1/responsesupstream response containsoutput[]item withtype == "image_generation_call"and non-emptyresult - THEN
OpenAIForwardResult.ImageCountequals the number of unique final image outputs - AND
OpenAIForwardResult.ImageSizeis the normalized image size tier
Scenario: Stream Responses output item is counted
- WHEN a stream
/v1/responsesupstream SSE event hastype == "response.output_item.done" - AND the event item has
type == "image_generation_call"and non-emptyresult - THEN the streaming result increments the unique final image output count
Scenario: Stream Responses completed output is counted
- WHEN a stream
/v1/responsesupstream SSE event hastype == "response.completed" - AND
response.output[]contains final image generation outputs - THEN the streaming result counts those images without double-counting images already seen in
response.output_item.done
Scenario: Partial image events are not billed as completed images
- WHEN a stream response contains
partial_imageevents - THEN those partial events do not increment
ImageCount - AND only final image generation outputs increment
ImageCount
Scenario: gpt-5.4 image tool request is billed as image
- WHEN a
/v1/responsesrequest usesmodel="gpt-5.4"ormodel="gpt-5.5" - AND the request includes an
image_generationtool - AND the upstream response contains one final image output
- THEN the usage log has
image_count=1 - AND the usage log has
billing_mode="image" - AND image pricing, not token pricing, determines
actual_cost
Scenario: Image output with zero usage is still billed
- WHEN an upstream Responses result contains final image output
- AND the upstream result has zero or missing token usage
- THEN the system writes a usage log
- AND the system bills using image pricing
Scenario: Responses image request records accompanying token usage
- WHEN a
/v1/responsesimage tool request returns final images and token usage - THEN the usage log records input tokens, output tokens, image output tokens, and image count
- AND the applied billing mode remains
image
Scenario: Responses image request does not introduce hybrid billing by default
- WHEN a
/v1/responsesimage tool request returns final images and text tokens - THEN the request is billed by image pricing under this change
- AND non-image token charges are not added unless a future explicit hybrid billing mode is implemented
Requirement: OpenAI Images API output accounting
The system SHALL count generated images from dedicated OpenAI Images API stream and non-stream paths and SHALL set ImageCount for successful image responses.
Scenario: Images non-stream data array is counted
- WHEN
/v1/images/generationsreturns a non-stream JSON response with top-leveldata[] - THEN
ImageCountequals the length ofdata[]
Scenario: Images stream data array is counted
- WHEN
/v1/images/generationsstream response emits SSE data containing top-leveldata[] - THEN
ImageCountequals the maximum final data array count observed for the request
Scenario: Images stream completed event is counted
- WHEN
/v1/images/generationsstream response emitsimage_generation.completedwith a final image payload - THEN the stream result counts one final image output
Scenario: Images stream Responses-form event is counted
- WHEN an Images API upstream path emits Responses-form
response.output_item.doneorresponse.completedevents with final image outputs - THEN the stream result counts final image outputs using the same de-duplication rules as Responses
Requirement: Channel image billing uses actual image count
The system SHALL use actual generated image count for channel billing_mode=image pricing and SHALL NOT bill multi-image requests as a single request.
Scenario: OpenAI channel image billing counts multiple images
- WHEN a channel image pricing entry resolves to unit price
0.25 - AND an OpenAI image request produces three images
- THEN
total_costis0.75before the selected image multiplier is applied - AND
RequestCountpassed into unified pricing is3
Scenario: Gateway channel image billing counts multiple images
- WHEN a non-OpenAI gateway image path produces two images
- AND channel image pricing resolves for the billing model
- THEN
RequestCountpassed into unified pricing is2
Scenario: Channel image pricing uses shared multiplier by default
- WHEN a channel image pricing entry resolves to unit price
0.25 - AND the group has ordinary effective multiplier
0.15 - AND the group has
image_rate_independent=false - AND the image request produces one image
- THEN
actual_costis0.0375
Scenario: Channel image pricing uses independent image multiplier when enabled
- WHEN a channel image pricing entry resolves to unit price
0.25 - AND the group has ordinary effective multiplier
0.15 - AND the group has
image_rate_independent=true - AND the group has
image_rate_multiplier=1 - AND the image request produces one image
- THEN
actual_costis0.25 - AND ordinary effective multiplier
0.15is not applied
Scenario: Account stats image pricing receives image count
- WHEN account stats pricing uses
billing_mode=image - AND the request produces multiple images
- THEN account stats cost is calculated with the actual image count
Requirement: Image size tier normalization
The system SHALL normalize OpenAI image sizes to explicit billing tiers for billing only. The system SHALL NOT reject requests locally because of an unknown or provider-invalid size; it SHALL forward the original size parameter upstream and let the official upstream API decide whether the request is valid.
Scenario: OpenAI 1024 square maps to 1K
- WHEN an OpenAI image request specifies
size="1024x1024" - THEN
ImageSizeis1K
Scenario: OpenAI landscape and portrait large sizes map to 2K
- WHEN an OpenAI image request specifies
1536x1024,1024x1536,1792x1024,1024x1792,2048x2048,2048x1152, or1152x2048 - THEN
ImageSizeis2K
Scenario: OpenAI gpt-image-2 4K presets map to 4K
- WHEN an OpenAI
gpt-image-2image request specifies3840x2160or2160x3840 - THEN
ImageSizeis4K
Scenario: OpenAI auto size maps to 2K
- WHEN an OpenAI image request omits size or specifies
size="auto" - THEN
ImageSizeis2K
Scenario: Custom OpenAI size is forwarded without local validation
- WHEN an OpenAI image request specifies a custom explicit
WIDTHxHEIGHTsize - THEN the system forwards the request upstream
- AND
ImageSizeis normalized to2Kor4Kfor billing
Scenario: Responses image tool without model uses default image billing model
- WHEN a
/v1/responsesrequest uses animage_generationtool withouttool.model - THEN image size validation and image billing use
gpt-image-2as the image billing model
Scenario: Invalid OpenAI size constraints are delegated upstream
- WHEN an OpenAI image request specifies an explicit size that fails OpenAI size constraints
- THEN the system forwards the request upstream
- AND any invalid-size error comes from the upstream provider response
Scenario: Custom OpenAI size tier mapping
- WHEN a custom size cannot be parsed as positive
WIDTHxHEIGHT - THEN
ImageSizeis2K - WHEN a custom size parses as positive
WIDTHxHEIGHT - AND
WIDTH * HEIGHTis no more than2560x1440 - THEN
ImageSizeis2K - WHEN a custom size parses as positive
WIDTHxHEIGHT - AND
WIDTH * HEIGHTexceeds2560x1440 - THEN
ImageSizeis4K
Requirement: Image usage log semantics
The system SHALL write usage logs for successful image generation with image billing metadata that matches the applied image pricing path.
Scenario: Image usage log records image billing mode
- WHEN a successful request has
ImageCount > 0 - THEN the usage log has
billing_mode="image" - AND the usage log records
image_count - AND the usage log records
image_sizewhen a normalized size tier is available
Scenario: Shared mode image usage log records shared multiplier
- WHEN a successful image request is billed with
image_rate_independent=false - AND the effective ordinary multiplier is
0.15 - THEN
usage_logs.rate_multiplieris0.15
Scenario: Independent mode image usage log records image multiplier
- WHEN a successful image request is billed with
image_rate_independent=true - AND
image_rate_multiplier=0.5 - THEN
usage_logs.rate_multiplieris0.5
Scenario: Token request usage log is unchanged
- WHEN a successful non-image token request is billed
- THEN
usage_logs.rate_multipliercontinues to record the ordinary token multiplier - AND
image_countis0