Skip to content

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

Merged
Wibias merged 50 commits into
lidge-jun:devfrom
harryzhou2000:feat/provider-cost-overlay
Aug 10, 2026
Merged

feat(usage): user-configurable per-model cost overlay (providers.<name>.modelCosts)#1010
Wibias merged 50 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 per-model provider pricing for input, output, cache reads, and cache writes.
    • Logs, Usage, dashboards, and CLI output identify configured pricing overrides.
    • Pricing persists through provider updates, migrations, OAuth re-login, and live edits.
    • Usage summaries refresh when pricing changes.
  • Bug Fixes

    • Added validation, fallback behavior, and display-only pricing.
    • Sensitive pricing identifiers are redacted from displayed configuration.
  • Documentation

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

    • Added translated pricing override labels and estimate messages.

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

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1c46da2b-34cb-4b4c-93cb-1000c11df55b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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, survive provider updates, and appear in localized Logs metadata.

Changes

Provider cost overlay

Layer / File(s) Summary
Overlay contracts and validation
src/types.ts, src/config.ts, src/server/auth-cors.ts, src/cli/*, src/usage/expected-prices.ts, docs-site/src/content/docs/.../providers.md, gui/src/pages/Logs.tsx, gui/src/i18n/*.ts, tests/provider-cost-overlay-config.test.ts, tests/cli-*
Defines four per-million-token rates, validates and sanitizes values, exposes safe dashboard and CLI data, and documents display-only behavior.
Registry synchronization
src/usage/user-cost-overlays.ts, src/usage/user-cost-overlay-reconciler.ts, src/config.ts, src/server/index.ts, src/server/lifecycle.ts, tests/user-cost-overlay-*.test.ts
Refreshes active overlays after configuration changes, persistence, live file reconciliation, and server lifecycle events.
Cost resolution and caching
src/usage/cost.ts, src/server/management/usage-summary-cache.ts, src/server/management/logs-usage-routes.ts, src/server/management/shared.ts, tests/usage-cost.test.ts, tests/api-usage.test.ts
Uses user overlays before built-in sources, propagates them through estimators, records provenance, and invalidates stale summaries.
Provider preservation and migration
src/oauth/*, src/providers/*, src/server/management/provider-routes.ts, tests/*provider*, tests/*login*
Preserves model costs during provider replacement, OAuth updates, key login, regional migration, and OpenAI legacy migration.
CI test isolation
.github/workflows/ci.yml, tests/zz-ci-api-usage-isolation.test.ts, tests/cli-restore-back.test.ts
Runs API usage coverage in a dedicated CI job and standardizes bounded CLI test execution.

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

Sequence Diagram(s)

sequenceDiagram
  participant ConfigLoader
  participant OverlayReconciler
  participant UserCostOverlays
  participant CostEstimator
  participant UsageSummaryCache
  participant Logs
  ConfigLoader->>OverlayReconciler: detect config.json changes
  OverlayReconciler->>UserCostOverlays: refresh modelCosts
  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: localize provider_cost_overlay
Loading

Possibly related PRs

Suggested reviewers: lidge-jun, ingwannu

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The CI workflow isolation changes and CLI restore test helper updates are unrelated to the provider cost overlay requirements in [#1009]. Move the CI and unrelated CLI test-helper changes to a separate pull request, unless they are required to support this feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation satisfies [#1009] by adding modelCosts, precedence and fall-through rules, validation, display-only estimates, refresh logic, cache invalidation, DTO exposure, localization, and tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding per-model, user-configurable cost overlays under provider configuration.
✨ 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
Contributor

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 Outdated
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 Outdated
harryzhou2000 and others added 12 commits August 10, 2026 04:30
The module-level poller started by startServer was only stopped in the
process-wide shutdown path; server.stop() (used by embedded callers and
tests) left the interval running with the stopped server's live config.
Stop it in the server.stop shutdown steps so no timer keeps updating
process-global overlay state after the listener is gone.
CodeRabbit follow-ups after rebasing onto the refcounted background
lifecycle:

- start the cost-overlay reconciler inside the guarded startup transaction
  so a listener bind failure releases its lease alongside backgroundLifecycle
- make the reconciler owner-scoped: each startServer registers its own live
  config and the shared timer stops only when the LAST owner releases, so
  stopping one of several servers cannot kill reconciliation for the others
- keep the process-wide stop in runListenerShutdown for full shutdown
…r stop

Wibias re-review (REQUEST CHANGES) found two reachable data-integrity
failures in the preservation lifecycle:

- With multiple servers, a newer owner can own a provider that an older
  owner still treats as disk-only; when the newer owner stops, the older
  owner's next unrelated save could erase the provider from disk. stop()
  now re-reads config and recomputes disk-only preservation against the
  remaining owners.
- When the final owner stops (or the process-wide stop runs), preserved
  disk-only providers stayed in the module cache, so a later save could
  resurrect an externally deleted provider. Final-owner/process-wide stop
  now clears the cache.

Also, reconcileUserCostOverlaysFromDisk no longer preserves every disk
provider when no live routing config is available (CodeRabbit outside-diff
finding): an overlay-only refresh must not turn later intentional provider
deletions into resurrected rows.

Regression coverage: A-lacks-beta/B-has-beta/B-stops/A-saves survives;
final-owner stop -> delete beta -> save does not resurrect; process-wide
stop -> delete beta -> save does not resurrect; overlay-only refresh with
no live config does not preserve disk providers.
- drainAndShutdown now releases only this server's reconciler lease via the
  startServer stop override; the process-wide stop stays test/teardown-only
  and is documented as such.
- startUserCostOverlayReconciler restarts the shared timer when a later
  owner requests a smaller interval and relaxes the cadence when it stops.
- key-login live-update test asserts the running proxy's live DTO retains
  the overlay, not just disk.
- reconcile tests wait on observed conditions instead of fixed sleeps and
  drop an ineffective in-memory mutation.
- usage-cost fall-through test no longer pins the vendor catalog rate.
… docs

- validLegacyOverlayCosts requires exactly the four Cost4 own fields, so a
  malformed legacy row with an extra field (e.g. apiKey) collides instead of
  being carried into canonical openai config.
- reconcileUserCostOverlaysFromDisk without a live config now mirrors the
  owners path: registered owners keep protecting disk-only rows, and with no
  live owners the stale preservation registry is cleared so a deleted
  provider cannot be resurrected by the next saveConfig.
- config-user-edits afterEach resets the module-level overlay registry.
- cadence regression test drops the timing-fragile negative assertion.
- providers docs (en/ko/ru/zh-cn) state custom providers may target any
  OpenAI-compatible endpoint through the openai-chat adapter.
- Capture the overlay version before reading/computing the summary and stamp
  that captured version; if the version changed mid-read, serve the summary
  uncached so a mixed-price entry is never accepted as current.
- Add a deterministic regression covering an overlay change during the
  read/summary lifecycle.
- Add the two new locale keys to the Turkish catalog after rebasing onto dev.
- configStamp() now includes ctimeMs and ino so a same-size edit inside one
  coarse mtime tick (or an atomic-rename replacement) still triggers a
  reconcile.
- usage-cost fall-through test no longer pins the expected-overlay rate.
- reconcile tests assert the child writer exit status and bound the first
  wait to 200ms so only the 20ms fast owner can satisfy it.
…r overlay wording

- Every provider validation issue path now passes the provider key through
  redactSecretString(name), matching the modelCosts path, so token-shaped
  provider keys cannot leak through ocx config validate/import diagnostics.
- Turkish overlay strings now say the price tier is user-configured
  (Kullanıcı tarafından yapılandırılan ...), consistent with ko/ru/zh.
rememberDiskOnlyProviders now preserves a disk provider whenever at least one
live owner lacks it, instead of dropping it as soon as any owner owns it.
One server's older live projection can no longer erase a provider owned by
another active server: an unrelated saveConfig from the older owner re-adds
the row through the shared preservation registry.

Regression added: A lacks beta -> B has beta -> both remain alive -> A saves
-> beta survives on disk.
Track provider ownership across live config projections so stale-owner preservation still protects externally added rows, while an owner that previously owned a provider can intentionally delete it. Successful deletion is propagated to all active preservation owners so a later stale save cannot resurrect the provider.

Regression covers A lacking beta, B/C owning beta, an unrelated A save preserving beta, a reconcile tick during B's delete gap, and B's explicit deletion surviving a later C save.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete for head af7937a2d5162e1aed6797ace6f9ee2aae702707. I will review pull request #1010.

✅ 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 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review pull request #1010 at head af7937a2d5162e1aed6797ace6f9ee2aae702707.

⚠️ 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
gui/src/i18n/ko.ts (1)

1936-1983: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Translate the new lab.* Compatibility Lab strings.

Lines 1936–1983 add the Compatibility Lab keys, but every value is untranslated English (e.g. "lab.title": "Compatibility Lab", "lab.verdict.UNKNOWN": "Unknown"). models.tab.compatibility and models.subtitle.compatibility, added by the same PR just above (lines 448-452), are correctly localized to Korean. Translate the lab.* block for consistency.

🤖 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 `@gui/src/i18n/ko.ts` around lines 1936 - 1983, Translate every newly added
lab.* value in the Korean locale, including titles, labels, statuses, verdicts,
layers, and messages, replacing the English text with natural Korean while
preserving all keys and interpolation or punctuation semantics.
gui/src/i18n/ja.ts (1)

1936-1983: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Translate the new lab.* Compatibility Lab strings.

Lines 1936–1983 add roughly 30 new keys, but every value is the untranslated English source text (for example, "lab.title": "Compatibility Lab", "lab.loadMore": "Load more", "lab.detailTitle": "Verdict detail"). Compare this to models.tab.compatibility and models.subtitle.compatibility, added in the same PR a few lines above, which are correctly localized to Japanese ("互換性", "ラボ投影証拠の読み取り専用互換性判定マトリクス。").

A Japanese-reading user opening the Compatibility Lab page sees a mix of Japanese chrome and English content strings. Translate these keys to match the rest of the catalog.

🤖 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 `@gui/src/i18n/ja.ts` around lines 1936 - 1983, Translate every newly added
lab.* value in the Japanese catalog from English into natural Japanese,
including titles, subtitles, statuses, filters, column labels,
empty/loading/error messages, detail actions, verdict labels, and evidence-layer
labels. Preserve all existing keys and interpolation or formatting while
matching the terminology used by models.tab.compatibility and
models.subtitle.compatibility.
gui/src/i18n/ru.ts (1)

1938-1985: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Translate the new lab.* Compatibility Lab strings.

Lines 1938–1985 add the Compatibility Lab keys with untranslated English values (e.g. "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence."), while models.tab.compatibility / models.subtitle.compatibility added by the same PR a few lines above are correctly localized to Russian. Translate the lab.* block for consistency.

🤖 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 `@gui/src/i18n/ru.ts` around lines 1938 - 1985, Translate every newly added
lab.* value in the Russian locale from English into natural Russian, including
titles, status labels, filters, column names, verdicts, layers, and messages.
Preserve all lab.* keys and placeholders while matching the existing Russian
terminology used by models.tab.compatibility and models.subtitle.compatibility.
gui/src/i18n/tr.ts (1)

1938-1984: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Translate the new lab.* Compatibility Lab strings.

Lines 1938–1984 add the Compatibility Lab keys with untranslated English values (e.g. "lab.title": "Compatibility Lab", "lab.col.protocol": "Protocol conformance"). models.tab.compatibility / models.subtitle.compatibility, added by the same PR at lines 453/457, are correctly localized to Turkish ("Uyumluluk", "Lab projeksiyon kanıtından salt okunur uyumluluk matrisi."). Translate the lab.* block for consistency.

🤖 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 `@gui/src/i18n/tr.ts` around lines 1938 - 1984, Translate every newly added
lab.* value in the Turkish locale, including titles, statuses, filters, column
labels, empty/loading/error messages, verdicts, and evidence layers, while
preserving all keys and interpolation or punctuation semantics. Use consistent
Turkish terminology with the existing models.tab.compatibility and
models.subtitle.compatibility translations.
gui/src/i18n/de.ts (1)

1943-1950: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Finish translating the Compatibility Lab detail-view strings.

Lines 1943–1950 leave lab.loadMore ("Load more"), lab.detailTitle ("Verdict detail"), lab.detailClose ("Close"), lab.detailSubject ("Subject"), lab.detailObservations ("Observations"), lab.detailEvents ("Contributing events"), lab.detailArtifacts ("Artifact metadata"), and lab.detailLoadFailed ("Could not load verdict detail") as untranslated English, while the surrounding lab.* keys in the same block (lines 1915-1942, 1951-1961) are correctly translated to German. A German-reading user who opens a verdict detail row sees English labels mixed into an otherwise German page.

Translate these eight strings to match the rest of the block.

🤖 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 `@gui/src/i18n/de.ts` around lines 1943 - 1950, Translate the eight English
values for lab.loadMore, lab.detailTitle, lab.detailClose, lab.detailSubject,
lab.detailObservations, lab.detailEvents, lab.detailArtifacts, and
lab.detailLoadFailed into German, matching the terminology and style used by the
surrounding lab.* translations while preserving all keys.
gui/src/i18n/zh.ts (1)

1936-1983: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Translate the new lab.* Compatibility Lab strings.

Lines 1936–1983 add the Compatibility Lab keys with untranslated English values (e.g. "lab.title": "Compatibility Lab", "lab.empty": "No compatibility verdicts in the projection yet."), while models.tab.compatibility / models.subtitle.compatibility added by the same PR a few lines above are correctly localized to Chinese ("兼容性", "来自实验室投影证据的只读兼容性判定矩阵。"). Translate the lab.* block for consistency.

🤖 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 `@gui/src/i18n/zh.ts` around lines 1936 - 1983, Translate every newly added
lab.* value in the zh locale, including titles, status and filter labels, column
headings, messages, verdicts, and evidence-layer names, into natural Chinese.
Preserve all existing keys and interpolation or punctuation structure, and align
terminology with the localized models.tab.compatibility and
models.subtitle.compatibility entries.
🤖 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.

Outside diff comments:
In `@gui/src/i18n/de.ts`:
- Around line 1943-1950: Translate the eight English values for lab.loadMore,
lab.detailTitle, lab.detailClose, lab.detailSubject, lab.detailObservations,
lab.detailEvents, lab.detailArtifacts, and lab.detailLoadFailed into German,
matching the terminology and style used by the surrounding lab.* translations
while preserving all keys.

In `@gui/src/i18n/ja.ts`:
- Around line 1936-1983: Translate every newly added lab.* value in the Japanese
catalog from English into natural Japanese, including titles, subtitles,
statuses, filters, column labels, empty/loading/error messages, detail actions,
verdict labels, and evidence-layer labels. Preserve all existing keys and
interpolation or formatting while matching the terminology used by
models.tab.compatibility and models.subtitle.compatibility.

In `@gui/src/i18n/ko.ts`:
- Around line 1936-1983: Translate every newly added lab.* value in the Korean
locale, including titles, labels, statuses, verdicts, layers, and messages,
replacing the English text with natural Korean while preserving all keys and
interpolation or punctuation semantics.

In `@gui/src/i18n/ru.ts`:
- Around line 1938-1985: Translate every newly added lab.* value in the Russian
locale from English into natural Russian, including titles, status labels,
filters, column names, verdicts, layers, and messages. Preserve all lab.* keys
and placeholders while matching the existing Russian terminology used by
models.tab.compatibility and models.subtitle.compatibility.

In `@gui/src/i18n/tr.ts`:
- Around line 1938-1984: Translate every newly added lab.* value in the Turkish
locale, including titles, statuses, filters, column labels, empty/loading/error
messages, verdicts, and evidence layers, while preserving all keys and
interpolation or punctuation semantics. Use consistent Turkish terminology with
the existing models.tab.compatibility and models.subtitle.compatibility
translations.

In `@gui/src/i18n/zh.ts`:
- Around line 1936-1983: Translate every newly added lab.* value in the zh
locale, including titles, status and filter labels, column headings, messages,
verdicts, and evidence-layer names, into natural Chinese. Preserve all existing
keys and interpolation or punctuation structure, and align terminology with the
localized models.tab.compatibility and models.subtitle.compatibility entries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c1c3a675-ec67-4335-8164-afc0763459ee

📥 Commits

Reviewing files that changed from the base of the PR and between 776d5b9 and af7937a.

📒 Files selected for processing (7)
  • 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/tr.ts
  • gui/src/i18n/zh.ts

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
gui/src/i18n/de.ts (1)

1943-1945: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate the remaining Compatibility Lab UI strings.

The German catalog still contains English controls, labels, and error text at Lines 1943-1945 and 1947-1950. This produces a mixed-language German UI.

Use German values such as Mehr laden, Urteilsdetails, Schließen, Beobachtungen, Beteiligte Ereignisse, Artefakt-Metadaten, and Details zum Urteil konnten nicht geladen werden.

As per path instructions, keep user-visible GUI strings in the i18n locale file and provide localized values for the German UI.

Proposed translation update
-  "lab.loadMore": "Load more",
-  "lab.detailTitle": "Verdict detail",
-  "lab.detailClose": "Close",
+  "lab.loadMore": "Mehr laden",
+  "lab.detailTitle": "Urteilsdetails",
+  "lab.detailClose": "Schließen",

-  "lab.detailObservations": "Observations",
-  "lab.detailArtifacts": "Artifact metadata",
-  "lab.detailLoadFailed": "Could not load verdict detail",
+  "lab.detailObservations": "Beobachtungen",
+  "lab.detailArtifacts": "Artefakt-Metadaten",
+  "lab.detailLoadFailed": "Details zum Urteil konnten nicht geladen werden",

Also applies to: 1947-1950

🤖 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 `@gui/src/i18n/de.ts` around lines 1943 - 1945, Update the German i18n entries
lab.loadMore, lab.detailTitle, lab.detailClose, and the adjacent Compatibility
Lab strings through the error message to use German translations, including Mehr
laden, Urteilsdetails, Schließen, Beobachtungen, Beteiligte Ereignisse,
Artefakt-Metadaten, and Details zum Urteil konnten nicht geladen werden.

Source: Path instructions

gui/src/i18n/ja.ts (1)

1936-1982: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Translate the Compatibility Lab (lab.*) block instead of copying the English source into every locale. Each locale file below declares itself a translated catalog for its language, but the entire lab.* block (lab.title through lab.layer.task_effectiveness, about 46 keys covering projection status, evidence filters, verdict records, detail views, verdict states, and evidence layers) is an exact copy of the English text from gui/src/i18n/en.ts. This compiles because every TKey is present, but it leaves the Compatibility Lab UI entirely in English for non-English users, and it contradicts each file's own AI-generated summary, which claims these strings were localized.

  • gui/src/i18n/ja.ts#L1936-L1982: translate the lab.* block into Japanese.
  • gui/src/i18n/ko.ts#L1936-L1983: translate the lab.* block into Korean.
  • gui/src/i18n/ru.ts#L1938-L1985: translate the lab.* block into Russian.
  • gui/src/i18n/tr.ts#L1938-L1985: translate the lab.* block into Turkish.
  • gui/src/i18n/zh.ts#L1936-L1983: translate the lab.* block into Chinese.
    As per path instructions, "user-visible strings go through the i18n locale files rather than hardcoded text" — the keys satisfy that mechanically, but the actual localized content is missing for this feature in every non-English locale.
🤖 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 `@gui/src/i18n/ja.ts` around lines 1936 - 1982, Translate the complete lab.*
Compatibility Lab block instead of retaining English source text: update
gui/src/i18n/ja.ts lines 1936-1982 in Japanese, gui/src/i18n/ko.ts lines
1936-1983 in Korean, gui/src/i18n/ru.ts lines 1938-1985 in Russian,
gui/src/i18n/tr.ts lines 1938-1985 in Turkish, and gui/src/i18n/zh.ts lines
1936-1983 in Chinese. Preserve every existing key from lab.title through
lab.layer.task_effectiveness, including status, filters, verdicts, details, and
evidence-layer labels.

Source: Path instructions

🤖 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 `@gui/src/i18n/ja.ts`:
- Around line 605-612: Update the Japanese translations for
logs.detail.source.user and its corresponding “was used” message around
logs.detail.source.user so both explicitly state that the provider price overlay
was configured by the user, not supplied by the provider. Preserve the existing
meaning and apply the wording consistently to both strings.

---

Outside diff comments:
In `@gui/src/i18n/de.ts`:
- Around line 1943-1945: Update the German i18n entries lab.loadMore,
lab.detailTitle, lab.detailClose, and the adjacent Compatibility Lab strings
through the error message to use German translations, including Mehr laden,
Urteilsdetails, Schließen, Beobachtungen, Beteiligte Ereignisse,
Artefakt-Metadaten, and Details zum Urteil konnten nicht geladen werden.

In `@gui/src/i18n/ja.ts`:
- Around line 1936-1982: Translate the complete lab.* Compatibility Lab block
instead of retaining English source text: update gui/src/i18n/ja.ts lines
1936-1982 in Japanese, gui/src/i18n/ko.ts lines 1936-1983 in Korean,
gui/src/i18n/ru.ts lines 1938-1985 in Russian, gui/src/i18n/tr.ts lines
1938-1985 in Turkish, and gui/src/i18n/zh.ts lines 1936-1983 in Chinese.
Preserve every existing key from lab.title through lab.layer.task_effectiveness,
including status, filters, verdicts, details, and evidence-layer labels.
🪄 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: 2dfe5393-1ffe-417a-9c1c-7ac2062daf48

📥 Commits

Reviewing files that changed from the base of the PR and between 776d5b9 and af7937a.

📒 Files selected for processing (7)
  • 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/tr.ts
  • gui/src/i18n/zh.ts

Comment thread gui/src/i18n/ja.ts
Wibias added 3 commits August 10, 2026 05:42
Stop the user cost overlay reconciler in api-usage afterEach so isolate workers do not keep a poll timer alive into later shard files. Harden cli-restore-back with spawn timeouts and isolated HOME for the help test, matching cli-provider budgets.
Exclude tests/api-usage.test.ts from sharded Linux test legs and run it in a fresh Bun process, matching the storage-policy isolation pattern. Prevents startServer overlay reconciler cycles from wedging shard 4 after cli-restore-back.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete for head c8409737526ab42f27f1a64932963de6a5cab42e. I will review pull request #1010.

✅ 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 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete for head c8409737526ab42f27f1a64932963de6a5cab42e. I will review pull request #1010.

⚠️ 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 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete for head c8409737526ab42f27f1a64932963de6a5cab42e. I will review pull request #1010.

⚠️ 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.

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed current head c840973 against current dev. The previous runtime and data-integrity blockers are fixed: cross-process edits reconcile live, disk-only providers survive unrelated saves across multiple owners, usage pricing invalidates safely, and the overlay remains display-only. I found no remaining runtime, security, or data-integrity blocker. One CodeRabbit thread is still a valid non-blocking test-strength nit: the invalid-config test should wait for the reconciler observation counter rather than readConfigDiagnostics() directly. Approval is for this exact head; merge should still require the in-progress exact-head macOS CI job to finish green.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot] PR #1010 is ready. CodeRabbit already completed review for head c8409737526ab42f27f1a64932963de6a5cab42e. No duplicate review request is needed.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review pull request #1010 at head 72b146bfd620c569aee3ecd0fcdf4c2b39386f05.

✅ 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 10, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete for head 72b146bfd620c569aee3ecd0fcdf4c2b39386f05. I will review pull request #1010.

⚠️ 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.

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the current exact head. The final live-reconcile regression now waits for the reconciler observation counter, all review threads are resolved, exact-head CI is green, and the current GitHub merge ref cleanly integrates with dev. The display-only pricing contract, live config reconciliation, cache invalidation, multi-owner preservation, and redaction boundaries all hold. Approved for merge.

Wibias commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Merged. Thanks @harryzhou2000 for sticking with this through the review iterations. 🙏

This is a genuinely useful addition: providers.<name>.modelCosts gives meaningful usage estimates for internal, custom, and OpenAI-compatible providers whose model IDs are missing from the built-in catalogs or whose real costs differ from public list prices. I especially like that it stays display-only and, after the hardening work, now handles live config edits, cache invalidation, multi-server persistence, and redaction safely.

@harryzhou2000

Copy link
Copy Markdown
Contributor Author

@Wibias — thanks for the thorough review and the smooth merge! Your feedback made the overlay reconciliation much more robust. 🙏

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)

3 participants