Skip to content

feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts) - #1010

Open
harryzhou2000 wants to merge 16 commits into
lidge-jun:devfrom
harryzhou2000:feat/provider-cost-overlay
Open

feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts)#1010
harryzhou2000 wants to merge 16 commits into
lidge-jun:devfrom
harryzhou2000:feat/provider-cost-overlay

Conversation

@harryzhou2000

@harryzhou2000 harryzhou2000 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes #1009

Summary

Adds providers.<name>.modelCosts — a per-model display price overlay (USD per
1M tokens) so operators can price internal/custom providers whose ids do not
match the compiled catalogs, or whose actual costs vary from list prices.

"providers": {
  "blsc": {
    "adapter": "openai-chat",
    "baseUrl": "https://llmapi.blsc.cn",
    "modelCosts": {
      "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 }
    }
  }
}

Resolution order: user modelCosts → jawcode catalog → expected-price overlay →
model-level vendor fallback. All-zero entries fall through. Display-time
estimation only; never billing.

Changes

  • src/usage/user-cost-overlays.ts (new): registry lifting
    providers.<name>.modelCosts into price-overlay rows; refreshed at
    loadConfig and every persist path; versioned so the estimator memo never
    serves stale rows and edits apply without a restart.
  • src/usage/cost.ts: user overlay wins in resolveMatchedPrice (exact
    provider/model match, source: "user"); memo key now includes the overlay
    version. Also replaces a stray NUL byte in the memo cache-key template
    literal with a space separator.
  • src/config.ts: providerModelCostsConfigError validation (non-negative
    finite 4-tuples) wired into the load-time schema refine.
  • src/server/auth-cors.ts: management API rejects malformed modelCosts;
    safeConfigDTO exposes the field.
  • src/server/management/shared.ts: new provider_cost_overlay estimate
    reason.
  • gui/: reason label + i18n strings (en/de/ja/ko/ru/zh).
  • Docs row in the providers reference.

UI change

Logs detail dialog showing the provider-configured price overlay

Tests

  • Usage-cost: user overlay beats jawcode/expected, custom providers resolve only
    via overlay, all-zero fall-through, combo fail-closed, registry refresh/memo
    invalidation.
  • Config: validation paths, load/save round-trip, registry refresh, management
    validation, DTO passthrough.

bun run typecheck, GUI eslint, and the touched suites pass (91 tests).

Summary by CodeRabbit

  • New Features

    • Added optional provider-specific pricing for exact models, including input, output, cache-read, and cache-write rates.
    • Logs estimates prioritize configured prices and indicate when overrides are applied.
    • Supports custom models with validation, zero-price fallback, and display-only pricing that does not affect billing.
    • Provider pricing settings are preserved during updates and migrations.
    • Usage summaries refresh when pricing overrides change.
  • Documentation

    • Documented configuration, validation, precedence, and fallback behavior.
  • Localization

    • Added translated labels for provider-configured pricing indicators.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@github-actions github-actions Bot changed the title feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts) [WRONG BRANCH] feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts) Aug 4, 2026
@github-actions
github-actions Bot marked this pull request as draft August 4, 2026 16:31
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds providers.<name>.modelCosts for exact model IDs. Validated prices populate a versioned runtime registry, override built-in cost sources, invalidate stale usage summaries, and update after configuration loads or persists. Logs reports provider-overlay estimates with localized labels.

Changes

Provider cost overlay

Layer / File(s) Summary
Overlay contracts and validation
src/types.ts, src/config.ts, src/server/auth-cors.ts, src/server/management/provider-routes.ts, src/providers/*, docs-site/src/content/docs/.../providers.md, tests/*
Defines four per-million-token rates, validates and sanitizes values, preserves costs during provider updates and migrations, exposes sanitized dashboard data, and documents display-only behavior.
Registry synchronization
src/usage/user-cost-overlays.ts, src/config.ts, tests/provider-cost-overlay-config.test.ts
Builds active overlay rows from provider configuration and refreshes them after configuration loads, repairs, fallbacks, diagnostics, and persistence.
Cost resolution and caching
src/usage/cost.ts, src/server/management/usage-summary-cache.ts, src/server/management/logs-usage-routes.ts, tests/usage-cost.test.ts, tests/api-usage.test.ts
Uses user overlays before built-in sources, tracks registry versions in memoization and usage-summary caches, propagates overlays through estimators, and preserves zero-price fallback.
Logs attribution and localization
src/server/management/shared.ts, gui/src/pages/Logs.tsx, gui/src/i18n/*.ts
Records provider_cost_overlay, maps the user price source, and adds localized Logs detail messages.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConfigLoader
  participant UserCostOverlays
  participant CostEstimator
  participant UsageSummaryCache
  participant Logs
  ConfigLoader->>UserCostOverlays: refreshUserCostOverlays(config)
  UserCostOverlays-->>CostEstimator: active overlays and version
  CostEstimator->>CostEstimator: resolve user price before built-in prices
  CostEstimator-->>UsageSummaryCache: store estimate with overlay version
  UsageSummaryCache->>UsageSummaryCache: reject stale overlay versions
  CostEstimator-->>Logs: estimate with source "user"
  Logs-->>Logs: map provider_cost_overlay to localized detail
Loading

Possibly related PRs

Suggested reviewers: lidge-jun, wibias

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies the linked issue by implementing configuration, validation, precedence, refresh, estimation, API, GUI, documentation, and tests for [#1009].
Out of Scope Changes check ✅ Passed The changes remain within scope because implementation, migrations, localization, documentation, API handling, and tests directly support the cost-overlay feature.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding user-configurable per-model cost overlays through providers..modelCosts.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/configuration/providers.md`:
- Line 69: Update the `modelCosts` documentation on line 69 to explicitly
clarify that custom or internal provider model IDs—even those absent from
built-in catalogs—are valid overlay keys for cost configuration. Add a note
stating that users can define custom prices for any model identifier regardless
of catalog presence, making clear that the feature supports providers beyond the
standard built-in offerings.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d0d55d83-385c-4beb-b349-119980acd24b

📥 Commits

Reviewing files that changed from the base of the PR and between f9b9440 and afc131d.

📒 Files selected for processing (16)
  • docs-site/src/content/docs/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx
  • src/config.ts
  • src/server/auth-cors.ts
  • src/server/management/shared.ts
  • src/types.ts
  • src/usage/cost.ts
  • src/usage/user-cost-overlays.ts
  • tests/provider-cost-overlay-config.test.ts
  • tests/usage-cost.test.ts

@harryzhou2000
harryzhou2000 force-pushed the feat/provider-cost-overlay branch from afc131d to 180b8b4 Compare August 4, 2026 16:41
@harryzhou2000
harryzhou2000 changed the base branch from main to dev August 4, 2026 16:42
@github-actions github-actions Bot changed the title [WRONG BRANCH] feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts) feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts) Aug 4, 2026
@github-actions
github-actions Bot marked this pull request as ready for review August 4, 2026 16:42
@github-actions github-actions Bot added the enhancement New feature or request label Aug 4, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/configuration/providers.md`:
- Line 75: Update the modelCosts documentation to state the complete
display-price fallback order: user configuration, jawcode catalog,
expected-price overlay, then model-level vendor fallback. Clarify that an
all-zero user entry falls through to the next source in that sequence, while
preserving the existing display-only and non-billing behavior.
- Line 75: Add the modelCosts configuration row after modelMaxOutputTokens in
the Japanese, Korean, Russian, and Simplified Chinese provider pages,
documenting exact model-ID keys, all-zero entries falling back to built-in
catalogs, and display-only estimates that never affect billing.

In `@gui/src/i18n/de.ts`:
- Line 574: Update the German translation value for
logs.detail.estimate.provider_cost_overlay to “Ein vom Anbieter konfiguriertes
Preis-Overlay wurde verwendet.”, preserving alignment with the English catalog
entry.

In `@gui/src/pages/Logs.tsx`:
- Around line 45-49: Extend the GUI price-source contract used by
MatchedPriceInfo to include "user", then add the logs.detail.source.user
translation key to every locale alongside the existing source labels so
provider-configured overlay-priced rows display a localized source.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a4b0f2de-a70c-4109-a5d9-f87dcbe73c8d

📥 Commits

Reviewing files that changed from the base of the PR and between afc131d and 180b8b4.

📒 Files selected for processing (8)
  • docs-site/src/content/docs/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx

Comment thread docs-site/src/content/docs/reference/configuration/providers.md Outdated
Comment thread gui/src/i18n/de.ts Outdated
Comment thread gui/src/pages/Logs.tsx

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 180b8b4326

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread gui/src/pages/Logs.tsx
Comment thread src/config.ts Outdated
@harryzhou2000

Copy link
Copy Markdown
Contributor Author

Thanks for the review — addressed in 7a4ce62:

  • Docstring coverage: JSDoc added to every function touched by this PR (loadConfig, persistConfigUnlocked, saveConfig, withRefreshedCostOverlays, safeConfigDTO, costResult, resolveMatchedPriceInner/Exact, estimateAttemptCost, validCost4, the Logs key helpers, plus the new DTO sanitizers). A local AST replica now reports 19/19 = 100% on the PR's new/modified functions.
  • Inline findings: GUI price-source contract extended with user and logs.detail.source.user in all six locales; German grammar fix; complete fallback order documented with the modelCosts row added to ja/ko/ru/zh-cn pages; safeConfigDTO serializes only the four rate fields per cost row (regression test added).
  • Verified: root typecheck clean, GUI eslint clean, 66 tests pass in the touched suites (usage-cost + model-costs config + management metrics + routing).

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/ja/reference/configuration/providers.md`:
- Line 68: Update the Cost4 documentation row in
docs-site/src/content/docs/ja/reference/configuration/providers.md:68-68 to list
the supported input, output, cacheRead, and cacheWrite rate fields. Apply the
equivalent field list or example to
docs-site/src/content/docs/ko/reference/configuration/providers.md:68-68,
docs-site/src/content/docs/ru/reference/configuration/providers.md:78-78, and
docs-site/src/content/docs/zh-cn/reference/configuration/providers.md:67-67,
preserving each locale’s language and existing pricing guidance.

In `@gui/src/i18n/ru.ts`:
- Line 566: Update the Russian translation for
logs.detail.estimate.provider_cost_overlay at line 592 to reuse the same
terminology from logs.detail.source.user at line 566. Replace the current
"настроенная пользователем цена провайдера" phrasing with a sentence form that
incorporates "Ценовой оверлей провайдера" (keeping the "оверлей" term
consistent). This aligns the Russian translations with every other locale in the
PR, which reuses an identical term across both the price-source label and the
estimate-reason explanation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a3d12d7c-bcdf-4344-b9a0-61f4e65190d7

📥 Commits

Reviewing files that changed from the base of the PR and between 180b8b4 and 7a4ce62.

📒 Files selected for processing (18)
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx
  • src/config.ts
  • src/server/auth-cors.ts
  • src/server/management/shared.ts
  • src/usage/cost.ts
  • src/usage/user-cost-overlays.ts
  • tests/provider-cost-overlay-config.test.ts

Comment thread docs-site/src/content/docs/ja/reference/configuration/providers.md Outdated
Comment thread gui/src/i18n/ru.ts
@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@github-actions
github-actions Bot marked this pull request as draft August 5, 2026 10:27

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/auth-cors.ts`:
- Around line 525-539: Update sanitizeModelCosts to create out with a null
prototype so assigning the "__proto__" model ID creates an own property and
Object.keys includes it. Add a regression test using JSON.parse() to construct
the "__proto__" key and verify safeConfigDTO exposes its valid cost row.

In `@tests/usage-cost.test.ts`:
- Around line 769-812: Move the empty-provider cleanup for user cost overlays
out of the test body and into an afterEach hook scoped to the surrounding
describe block. Ensure the hook calls refreshUserCostOverlays with an empty
providers object so the blsc overlay is reset even when assertions in “registry
refresh replaces rows, bumps the version, and invalidates the memo” fail, and
update the bun:test imports to include afterEach.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d8697a9c-f003-4c14-ae6a-70292ae50aef

📥 Commits

Reviewing files that changed from the base of the PR and between 8034cd7 and f620f7f.

📒 Files selected for processing (20)
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx
  • src/config.ts
  • src/server/auth-cors.ts
  • src/server/management/shared.ts
  • src/types.ts
  • src/usage/cost.ts
  • src/usage/user-cost-overlays.ts
  • tests/provider-cost-overlay-config.test.ts
  • tests/usage-cost.test.ts

Comment thread src/server/auth-cors.ts
Comment thread tests/usage-cost.test.ts
@harryzhou2000

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume — the dev merge (f620f7f) resolved the config.ts conflict (persistConfigUnlocked now returns boolean for generation bumping while still refreshing the cost-overlay registry). Please run the full review on the merged state.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@harryzhou2000 I will resume review and perform a full review of the merged state, including the persistConfigUnlocked generation and cost-overlay refresh behavior.

✅ Action performed

Reviews resumed.


Full review finished.

@harryzhou2000

Copy link
Copy Markdown
Contributor Author

Heads-up for review: the hygiene gate flags src/server/auth-cors.ts as an auth surface (unsponsored_surface) because this PR adds management-API validation for modelCosts and exposes the field in safeConfigDTO. The change is read/validation-only — no credential handling changes — but per MAINTAINERS.md it needs the maintainer-sponsored label once reviewed. Could you apply it when you take a look?

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/server/auth-cors.ts (1)

525-539: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the valid __proto__ model ID.

Line 527 creates a normal object. providerModelCostsConfigError accepts "__proto__" because it is a nonblank model ID. For a row parsed from JSON, Line 536 changes out's prototype instead of adding an own property. Object.keys(out) then omits the row, so safeConfigDTO does not expose a valid configured price.

Create out with a null prototype. Add a regression test that builds the key through JSON.parse().

Proposed fix
-  const out: Record<string, ProviderCostOverlay> = {};
+  const out: Record<string, ProviderCostOverlay> = Object.create(null);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/auth-cors.ts` around lines 525 - 539, Update sanitizeModelCosts to
create out with a null prototype so assigning the valid "__proto__" model ID
produces an own property and remains included in the returned configuration. Add
a regression test that obtains this key via JSON.parse() and verifies the
sanitized costs preserve the valid entry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/provider-cost-overlay-config.test.ts`:
- Around line 26-30: Reset the user overlay registry in both affected test
sites: in tests/provider-cost-overlay-config.test.ts lines 26-30, call
refreshUserCostOverlays({ providers: {} } as OcxConfig) in the existing
afterEach before deleting OPENCODEX_HOME; in tests/usage-cost.test.ts lines
769-812, add a scoped afterEach that performs the same reset and remove the
test-body cleanup near line 807.

---

Duplicate comments:
In `@src/server/auth-cors.ts`:
- Around line 525-539: Update sanitizeModelCosts to create out with a null
prototype so assigning the valid "__proto__" model ID produces an own property
and remains included in the returned configuration. Add a regression test that
obtains this key via JSON.parse() and verifies the sanitized costs preserve the
valid entry.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a262235e-fcc4-491e-a174-d1c80bdad0fb

📥 Commits

Reviewing files that changed from the base of the PR and between 8034cd7 and f620f7f.

📒 Files selected for processing (20)
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx
  • src/config.ts
  • src/server/auth-cors.ts
  • src/server/management/shared.ts
  • src/types.ts
  • src/usage/cost.ts
  • src/usage/user-cost-overlays.ts
  • tests/provider-cost-overlay-config.test.ts
  • tests/usage-cost.test.ts

Comment thread tests/provider-cost-overlay-config.test.ts
@github-actions
github-actions Bot marked this pull request as ready for review August 5, 2026 11:46

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5db9f883f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/usage/user-cost-overlays.ts Outdated
Comment thread src/config.ts
@github-actions
github-actions Bot marked this pull request as draft August 5, 2026 13:06
@github-actions
github-actions Bot marked this pull request as ready for review August 5, 2026 13:09

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

const userOverlay = findExpectedPriceOverlay(provider, modelId, userOverlays);

P2 Badge Try exact provider names before collapsing user overlays

When a valid custom provider name happens to end with the Codex account-label suffix pattern, such as blsc-pabcdef, resolveMatchedPrice() has already collapsed it to blsc before this new user-overlay lookup runs, while refreshUserCostOverlays() stores the configured row under the exact provider name. In that scenario a valid providers.blsc-pabcdef.modelCosts.custom-model entry is never matched, so Logs/usage estimates stay unpriced despite the explicit override; try the exact provider against userOverlays before applying baseProviderLabel, or register both exact and collapsed keys.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/config.ts Outdated
Comment thread src/config.ts
… isolation

- sanitizeModelCosts builds the DTO map with a null prototype so a model id
  literally named __proto__ stays an own row instead of mutating the map's
  prototype and vanishing from Object.keys (CodeRabbit minor).
- usage-cost and provider-cost-overlay-config tests reset the module-level
  overlay registry in afterEach so rows cannot leak across test files in a
  shared-process run (CodeRabbit stability).
- Regression test: safeConfigDTO keeps a __proto__ model id as an own row.
Codex review findings:

- refreshUserCostOverlays now copies ONLY the four validated rate fields
  into the overlay row, so a hand-edited row carrying extra properties
  (e.g. a misplaced apiKey) can no longer leak through /api/logs display
  estimates (P1).
- loadConfig/configDiagnosticsFromRaw run sanitizeModelCostsForLoad before
  schema validation: malformed display-price rows are dropped with a warning
  instead of failing the whole parse and falling back to defaults, which
  previously discarded otherwise valid providers. Strict rejection stays at
  the management/write boundary (P2).

Regression tests: malformed row degradation, non-object modelCosts drop, and
registry rows containing only the four rate fields.
A custom provider whose name ends with the Codex account-log-label suffix
pattern (e.g. blsc-pabcdef) had its provider collapsed by baseProviderLabel
before the user-overlay lookup, so providers.<name>.modelCosts rows stored
under the exact name never matched and estimates stayed unpriced. resolveMatchedPrice now checks the exact provider against the user overlay first, then collapses for the compiled catalogs.
…y changes

- providerModelCostsConfigError now JSON-quotes and redacts secret-shaped
  model ids so a malformed write cannot echo a pasted key/secret back
  through the management API.
- /api/usage summaries are cached against userCostOverlayVersion(): an
  overlay save invalidates the entry even when the usage log is unchanged.
- refreshUserCostOverlays is a no-op when the extracted rows are
  byte-identical, so reloads of an unchanged config (server start,
  migrations, persist paths) no longer churn the version, invalidate the
  summary cache, or thash the cost memo.
- tests: redaction + quoted-key assertions, cache-invalidation test, and
  an identical-refresh no-op regression test.
…t finally block

The test installs a module-level blsc overlay; reset it to empty before
stopping the server so a later test (or an assertion/shutdown failure)
cannot resolve user-configured prices unexpectedly.
providerManagementConfigError echoed the caller-controlled provider name
verbatim in the modelCosts error path even though the route has not yet
validated/sanitized it. JSON-quote and redact the name (same rule as the
retryOn429 branch) so a token-shaped provider name cannot serialize back
through the management API. Regression test added.
…ration

- /api/providers POST now carries an existing provider's modelCosts when the
  overwrite payload omits it, so the dashboard's add/edit form cannot silently
  erase hand-edited per-model price overlays (same rule as the apiKeyPool
  carry-over).
- The Alibaba region startup migration carries modelCosts in USER_OWNED_FIELDS
  so an intl migration does not drop user price overlays.
- providers.md (en/ja/ko/ru/zh-cn) now states that custom, local
  OpenAI-compatible, and internal providers support exact model-id overlays
  and that overlays affect display-time estimates only — never routing,
  account selection, quotas, or billing. zh-cn wording fixed.
- ko/zh i18n align provider terminology with logs.col.provider.
- Regression tests for both carry-over paths; OcxConfig type import added.
validateConfigCandidate (ocx config validate/import) serializes the issue
path as providers.<name>.modelCosts; a token-shaped provider key could leak
through the CLI error even though model ids inside the message are redacted.
The schema issue path now runs the provider name through redactSecretString.
Regression test in tests/provider-cost-overlay-config.test.ts.
…gistry provenance

- mergeLegacyOpenAiProviderRows now carries modelCosts from the openai and
  openai-multi rows, and managedLegacyMultiOverlay accepts modelCosts as a
  managed overlay field, so a v1/restored config with user price overlays no
  longer drops them (or collides) during the tier migration.
- refreshUserCostOverlays redacts token-shaped provider/model ids in the
  display-only source string and in the refresh signature, so raw pasted-key
  identifiers never live in registry metadata or cache keys; matching still
  uses the raw fields.
- Regression tests for both.
@harryzhou2000
harryzhou2000 force-pushed the feat/provider-cost-overlay branch from dbf1226 to ea7f5a6 Compare August 6, 2026 14:26
@github-actions
github-actions Bot marked this pull request as ready for review August 6, 2026 14:27
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate passed. I will review the current pull request head.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate completed for ea7f5a69748c666f739143142627f8ace1fcb271. I will review the current PR head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/auth-cors.ts`:
- Around line 534-550: Update sanitizeModelCosts to detect and omit
secret-shaped model IDs before adding entries to the output DTO, reusing the
existing token-shape validation used by providerModelCostsConfigError where
available. Preserve valid model-cost rows, and add a regression test confirming
token-shaped IDs such as sk-abcdef1234567890 are absent from safeConfigDTO.

In `@src/usage/user-cost-overlays.ts`:
- Around line 76-85: The signature in the overlay refresh logic must compare raw
provider, modelId, and all four cost rates so distinct token-shaped IDs trigger
updates; retain only source redaction for display. Update the signature
construction near the refresh function, preserve the activeSignature/version
behavior, and add a regression test that refreshes two different redacted IDs
and verifies the second ID resolves.

In `@tests/openai-provider-option-migration.test.ts`:
- Around line 172-183: Update the test around projectOpenAiTierMigration to
assert the complete merged modelCosts map, including both the openai costs and
the openai-multi multiCosts entry. Replace the single-provider equality check
while preserving the expected combined values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 86dc4793-5134-471b-863f-af216ff4d956

📥 Commits

Reviewing files that changed from the base of the PR and between e9d957b and ea7f5a6.

⛔ Files ignored due to path filters (1)
  • docs/screenshots/provider-cost-overlay-logs-detail.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/pages/Logs.tsx
  • src/config.ts
  • src/providers/alibaba-region-migration.ts
  • src/providers/openai-tiers.ts
  • src/server/auth-cors.ts
  • src/server/management/logs-usage-routes.ts
  • src/server/management/provider-routes.ts
  • src/server/management/shared.ts
  • src/server/management/usage-summary-cache.ts
  • src/types.ts
  • src/usage/cost.ts
  • src/usage/user-cost-overlays.ts
  • tests/alibaba-region-migration.test.ts
  • tests/api-usage.test.ts
  • tests/management-provider-validation.test.ts
  • tests/openai-provider-option-migration.test.ts
  • tests/provider-cost-overlay-config.test.ts
  • tests/usage-cost.test.ts

Comment thread src/server/auth-cors.ts
Comment thread src/usage/user-cost-overlays.ts Outdated
Comment thread tests/openai-provider-option-migration.test.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea7f5a6974

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/server/auth-cors.ts
Comment thread src/usage/user-cost-overlays.ts Outdated
Comment thread src/providers/openai-tiers.ts Outdated
@harryzhou2000
harryzhou2000 marked this pull request as draft August 6, 2026 14:57
…d legacy merge

Review round 8b230c8 findings:

- safeConfigDTO redacts secret-shaped model ids in modelCosts keys so the
  dashboard DTO cannot echo a pasted key (validation errors already redacted).
- The overlay refresh signature compares RAW matching fields again: two
  distinct secret-shaped ids must not collapse to the same redacted signature
  and skip the version bump (process-local signature; only the display source
  stays redacted).
- providerManagementConfigError tolerates modelCosts on the canonical openai
  seed (validated separately), so management clients can add overlays.
- mergeLegacyOpenAiProviderRows merges disjoint modelCosts from both legacy
  rows instead of nullish-picking one map and dropping the other.
- Tests for every case, including a distinct-id change-detection regression.
…hape check

Local multi-model audit (deepseek-v4-flash, GLM-5.2) findings:

- mergeLegacyOpenAiProviderRows no longer attaches a spurious empty
  modelCosts: {} when neither legacy row carries an overlay (empty object is
  truthy); the minimal tier-1 migration stays clean.
- managedLegacyMultiOverlay validates the legacy modelCosts shape locally
  (no config.ts import — that would cycle) so a malformed overlay is a
  collision instead of being carried into the canonical row.
- safeConfigDTO drops secret-shaped model ids from modelCosts entirely
  instead of collapsing distinct rows into one [REDACTED] placeholder key.
- Comment on the raw change-detection signature corrected.
- Tests: no-empty-overlay assertion, DTO drop assertions, and a
  loadConfig-unchanged no-op version test.
@harryzhou2000
harryzhou2000 marked this pull request as ready for review August 6, 2026 15:23
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review the current pull request head.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review the current pull request head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review the current pull request head, including configuration validation, overlay precedence, cache invalidation, management DTO handling, and display-only cost behavior.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca12e9ee46

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gui/src/pages/Logs.tsx
Comment thread docs-site/src/content/docs/reference/configuration/providers.md Outdated
- logs.detail.matchedKey is now source-neutral ("Matched price key") in all
  six locales: it is also rendered when price.source is "user", where no
  jawcode row was matched.
- providers.md (en/ja/ko/ru/zh-cn) now documents that modelCosts also reprices
  Usage totals, including historical entries, so a price edit can move past
  aggregates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request maintainer-sponsored Maintainer sponsors this change to an auth, workflow, release, or dependency surface review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts)

2 participants