Skip to content

Add request-level price modifiers - #445

Open
Kludex wants to merge 6 commits into
mainfrom
codex/request-level-price-modifiers
Open

Add request-level price modifiers#445
Kludex wants to merge 6 commits into
mainfrom
codex/request-level-price-modifiers

Conversation

@Kludex

@Kludex Kludex commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

  • add request-level pricing context and ordered model price modifiers for Python and JS
  • support extracted pricing context values from provider usage payloads
  • update provider/data schemas and add focused Python and JS tests

Validation

  • uv run pytest
  • pre-commit hooks: ruff, prettier, JS lint, Python typecheck, TypeScript typecheck, build-prices

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 15 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/js/src/engine.ts Outdated
Comment thread packages/python/genai_prices/types.py
Comment thread packages/python/genai_prices/types.py Outdated
Comment thread prices/providers/.schema.json Outdated
Comment thread prices/data_slim.schema.json Outdated

@alexmojaki alexmojaki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to have a meeting to discuss this

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 16 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="prices/providers/.schema.json">

<violation number="1" location="prices/providers/.schema.json:211">
P2: The `ConditionalPrice.constraint` description only mentions timestamps, but the field now also accepts `PriceContextConstraint` (request-level context matching like batch mode).</violation>
</file>

<file name="prices/data_slim.schema.json">

<violation number="1" location="prices/data_slim.schema.json:211">
P2: The `ConditionalPrice.constraint.description` says "Timestamp when this price starts, None means this price is always valid." but the `anyOf` now also accepts `PriceContextConstraint`, which is not a timestamp. Update the description to reflect both constraint types, e.g.: "Constraint that defines when this price applies. Can be a timestamp or a pricing context filter."</violation>
</file>

<file name="packages/js/src/engine.ts">

<violation number="1" location="packages/js/src/engine.ts:176">
P2: A malformed or future constraint type can now crash price resolution instead of being skipped, because the new branch dereferences `constraint.price_context` without a type guard. Consider gating this branch on `constraint.type === 'price_context'` before calling `matchesContext`.</violation>
</file>

<file name="prices/providers/anthropic.yml">

<violation number="1" location="prices/providers/anthropic.yml:79">
P3: Looking at this change — `prices_checked: 2025-11-06` was kept as-is while adding new batch pricing entries. Since this is a pricing update (adding batch rates that didn't exist in the data before), `prices_checked` should be updated to the current date per the project convention in `prices/README.md`.</violation>
</file>

<file name="prices/data.schema.json">

<violation number="1" location="prices/data.schema.json:212">
P2: The `constraint` field description on `ConditionalPrice` is stale now that `PriceContextConstraint` is a valid option. It still reads "Timestamp when this price starts..." which only describes `StartDateConstraint` and `TimeOfDateConstraint`. Update the description so downstream consumers know the constraint can also be a request-level pricing context match.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

{
"$ref": "#/$defs/TimeOfDateConstraint"
},
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The ConditionalPrice.constraint description only mentions timestamps, but the field now also accepts PriceContextConstraint (request-level context matching like batch mode).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prices/providers/.schema.json, line 211:

<comment>The `ConditionalPrice.constraint` description only mentions timestamps, but the field now also accepts `PriceContextConstraint` (request-level context matching like batch mode).</comment>

<file context>
@@ -207,6 +207,9 @@
             {
               "$ref": "#/$defs/TimeOfDateConstraint"
+            },
+            {
+              "$ref": "#/$defs/PriceContextConstraint"
             }
</file context>

{
"$ref": "#/$defs/TimeOfDateConstraint"
},
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The ConditionalPrice.constraint.description says "Timestamp when this price starts, None means this price is always valid." but the anyOf now also accepts PriceContextConstraint, which is not a timestamp. Update the description to reflect both constraint types, e.g.: "Constraint that defines when this price applies. Can be a timestamp or a pricing context filter."

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prices/data_slim.schema.json, line 211:

<comment>The `ConditionalPrice.constraint.description` says "Timestamp when this price starts, None means this price is always valid." but the `anyOf` now also accepts `PriceContextConstraint`, which is not a timestamp. Update the description to reflect both constraint types, e.g.: "Constraint that defines when this price applies. Can be a timestamp or a pricing context filter."</comment>

<file context>
@@ -207,6 +207,9 @@
             {
               "$ref": "#/$defs/TimeOfDateConstraint"
+            },
+            {
+              "$ref": "#/$defs/PriceContextConstraint"
             }
</file context>

Comment thread packages/js/src/engine.ts
Comment on lines +176 to +179
} else if (
matchesContext(constraint.price_context, priceContext) &&
!(constraint.not_price_context && matchesContext(constraint.not_price_context, priceContext))
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A malformed or future constraint type can now crash price resolution instead of being skipped, because the new branch dereferences constraint.price_context without a type guard. Consider gating this branch on constraint.type === 'price_context' before calling matchesContext.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/js/src/engine.ts, line 176:

<comment>A malformed or future constraint type can now crash price resolution instead of being skipped, because the new branch dereferences `constraint.price_context` without a type guard. Consider gating this branch on `constraint.type === 'price_context'` before calling `matchesContext`.</comment>

<file context>
@@ -174,80 +173,16 @@ export function getActiveModelPrice(model: ModelInfo, timestamp: Date, priceCont
             break
           }
         }
+      } else if (
+        matchesContext(constraint.price_context, priceContext) &&
+        !(constraint.not_price_context && matchesContext(constraint.not_price_context, priceContext))
</file context>
Suggested change
} else if (
matchesContext(constraint.price_context, priceContext) &&
!(constraint.not_price_context && matchesContext(constraint.not_price_context, priceContext))
) {
} else if (
constraint.type === 'price_context' &&
matchesContext(constraint.price_context, priceContext) &&
!(constraint.not_price_context && matchesContext(constraint.not_price_context, priceContext))
) {

Comment thread prices/data.schema.json
"$ref": "#/$defs/TimeOfDateConstraint"
},
{
"$ref": "#/$defs/PriceContextConstraint"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The constraint field description on ConditionalPrice is stale now that PriceContextConstraint is a valid option. It still reads "Timestamp when this price starts..." which only describes StartDateConstraint and TimeOfDateConstraint. Update the description so downstream consumers know the constraint can also be a request-level pricing context match.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prices/data.schema.json, line 212:

<comment>The `constraint` field description on `ConditionalPrice` is stale now that `PriceContextConstraint` is a valid option. It still reads "Timestamp when this price starts..." which only describes `StartDateConstraint` and `TimeOfDateConstraint`. Update the description so downstream consumers know the constraint can also be a request-level pricing context match.</comment>

<file context>
@@ -207,6 +207,9 @@
               "$ref": "#/$defs/TimeOfDateConstraint"
+            },
+            {
+              "$ref": "#/$defs/PriceContextConstraint"
             }
           ],
</file context>

output_mtok: 4
- constraint:
price_context:
service_tier: batch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Looking at this change — prices_checked: 2025-11-06 was kept as-is while adding new batch pricing entries. Since this is a pricing update (adding batch rates that didn't exist in the data before), prices_checked should be updated to the current date per the project convention in prices/README.md.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prices/providers/anthropic.yml, line 79:

<comment>Looking at this change — `prices_checked: 2025-11-06` was kept as-is while adding new batch pricing entries. Since this is a pricing update (adding batch rates that didn't exist in the data before), `prices_checked` should be updated to the current date per the project convention in `prices/README.md`.</comment>

<file context>
@@ -69,10 +69,19 @@ models:
+          output_mtok: 4
+      - constraint:
+          price_context:
+            service_tier: batch
+        prices:
+          input_mtok: 0.4
</file context>

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.

2 participants