Conversation
Re-introduces the BYOK fee that was removed in 6a37a4c, now at 5% (previously 1%). When users use their own provider API keys, 5% of the tracked cost is deducted from their organization credits. The fee is configurable via the BYOK_FEE_PERCENTAGE environment variable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughThis PR introduces BYOK (Bring Your Own Keys) fee handling across the platform. It adds a 5% tracking fee configuration variable, exports it for application-wide use, updates user-facing copy to reflect the fee structure, and implements fee deduction logic in the worker service for api-keys mode log processing. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/worker/src/log-processing.spec.ts (1)
157-160: Avoid hardcoding the BYOK percentage in the test.Using
0.05directly can drift from runtime/shared config and miss future percentage updates.♻️ Proposed adjustment
+import { BYOK_FEE_PERCENTAGE } from "@llmgateway/shared"; @@ - const byokFeePercentage = 0.05; // 5% - const expectedFee = cost * byokFeePercentage; + const expectedFee = cost * BYOK_FEE_PERCENTAGE;Also applies to: 187-187
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/worker/src/log-processing.spec.ts` around lines 157 - 160, The test hardcodes the BYOK fee percent (byokFeePercentage = 0.05) which can drift from runtime config; update the test to pull the percentage from the shared runtime/config symbol (e.g., BYOK_FEE_PERCENTAGE or getByokFeePercentage) instead of using 0.05, then compute expectedFee = cost * <shared symbol>; also replace the other hardcoded occurrence noted (around the second location) so both tests derive the percentage from the same shared constant/function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/shared/src/fees.ts`:
- Around line 15-17: The BYOK_FEE_PERCENTAGE export currently parses the env var
directly which can produce NaN or out-of-range values; update the code around
the BYOK_FEE_PERCENTAGE constant to (1) read the raw env string, (2) parse it to
a number and check isFinite, (3) default to 0.05 if invalid, and (4) clamp the
resulting numeric value to the valid range [0, 1] before exporting; reference
BYOK_FEE_PERCENTAGE to locate the change and ensure any logging or thrown errors
are handled consistently with existing patterns.
---
Nitpick comments:
In `@apps/worker/src/log-processing.spec.ts`:
- Around line 157-160: The test hardcodes the BYOK fee percent
(byokFeePercentage = 0.05) which can drift from runtime config; update the test
to pull the percentage from the shared runtime/config symbol (e.g.,
BYOK_FEE_PERCENTAGE or getByokFeePercentage) instead of using 0.05, then compute
expectedFee = cost * <shared symbol>; also replace the other hardcoded
occurrence noted (around the second location) so both tests derive the
percentage from the same shared constant/function.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
.env.exampleapps/ui/src/components/landing/faq.tsxapps/ui/src/components/landing/pricing-plans.tsxapps/ui/src/components/pricing/pricing-table.tsxapps/worker/src/log-processing.spec.tsapps/worker/src/worker.tspackages/shared/src/fees.tspackages/shared/src/index.ts
| export const BYOK_FEE_PERCENTAGE = parseFloat( | ||
| process.env.BYOK_FEE_PERCENTAGE ?? "0.05", | ||
| ); |
There was a problem hiding this comment.
Validate and bound BYOK fee config before export.
parseFloat here can yield NaN or out-of-range values, which can silently break or distort deductions in worker billing paths.
🔧 Proposed fix
+const DEFAULT_BYOK_FEE_PERCENTAGE = 0.05;
+const rawByokFeePercentage = Number(
+ process.env.BYOK_FEE_PERCENTAGE ?? DEFAULT_BYOK_FEE_PERCENTAGE.toString(),
+);
+
+if (
+ !Number.isFinite(rawByokFeePercentage) ||
+ rawByokFeePercentage < 0 ||
+ rawByokFeePercentage > 1
+) {
+ throw new Error(
+ `Invalid BYOK_FEE_PERCENTAGE "${process.env.BYOK_FEE_PERCENTAGE}". Expected a number between 0 and 1.`,
+ );
+}
+
-export const BYOK_FEE_PERCENTAGE = parseFloat(
- process.env.BYOK_FEE_PERCENTAGE ?? "0.05",
-);
+export const BYOK_FEE_PERCENTAGE = rawByokFeePercentage;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const BYOK_FEE_PERCENTAGE = parseFloat( | |
| process.env.BYOK_FEE_PERCENTAGE ?? "0.05", | |
| ); | |
| const DEFAULT_BYOK_FEE_PERCENTAGE = 0.05; | |
| const rawByokFeePercentage = Number( | |
| process.env.BYOK_FEE_PERCENTAGE ?? DEFAULT_BYOK_FEE_PERCENTAGE.toString(), | |
| ); | |
| if ( | |
| !Number.isFinite(rawByokFeePercentage) || | |
| rawByokFeePercentage < 0 || | |
| rawByokFeePercentage > 1 | |
| ) { | |
| throw new Error( | |
| `Invalid BYOK_FEE_PERCENTAGE "${process.env.BYOK_FEE_PERCENTAGE}". Expected a number between 0 and 1.`, | |
| ); | |
| } | |
| export const BYOK_FEE_PERCENTAGE = rawByokFeePercentage; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/shared/src/fees.ts` around lines 15 - 17, The BYOK_FEE_PERCENTAGE
export currently parses the env var directly which can produce NaN or
out-of-range values; update the code around the BYOK_FEE_PERCENTAGE constant to
(1) read the raw env string, (2) parse it to a number and check isFinite, (3)
default to 0.05 if invalid, and (4) clamp the resulting numeric value to the
valid range [0, 1] before exporting; reference BYOK_FEE_PERCENTAGE to locate the
change and ensure any logging or thrown errors are handled consistently with
existing patterns.
There was a problem hiding this comment.
Pull request overview
Re-introduces billing for BYOK (api-keys mode) by deducting an additional organization-credit fee (default 5% of tracked request cost), and updates configuration/docs/UI copy accordingly.
Changes:
- Adds
BYOK_FEE_PERCENTAGE(default0.05) to shared fees exports, sourced fromprocess.env. - Updates worker batch log processing to deduct BYOK fee (+ storage cost) for
api-keysmode logs. - Updates tests,
.env.example, and UI marketing copy to reflect the 5% BYOK fee.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/index.ts | Re-exports BYOK_FEE_PERCENTAGE from shared package entrypoint. |
| packages/shared/src/fees.ts | Introduces env-configurable BYOK_FEE_PERCENTAGE (default 0.05). |
| apps/worker/src/worker.ts | Applies BYOK fee deduction during batch log processing for api-keys usage. |
| apps/worker/src/log-processing.spec.ts | Updates expectations to reflect BYOK fee deduction for api-keys logs. |
| apps/ui/src/components/pricing/pricing-table.tsx | Updates pricing table copy from “Included” to “5% fee” for BYOK. |
| apps/ui/src/components/landing/pricing-plans.tsx | Updates landing pricing plan feature text to “BYOK (5% fee)”. |
| apps/ui/src/components/landing/faq.tsx | Updates FAQ copy to reflect BYOK tracking fee. |
| .env.example | Documents/introduces BYOK_FEE_PERCENTAGE=0.05 configuration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // In API keys mode, charge BYOK fee (% of tracked cost) + storage cost | ||
| let totalToDeduct = new Decimal(0); | ||
|
|
There was a problem hiding this comment.
There’s a nearby comment just above this block that still states API keys mode “only deduct[s] storage cost”. Since this logic now also applies a BYOK fee, please update that comment to reflect the current billing rules (credits: full cost; api-keys: BYOK fee + storage cost).
| export const BYOK_FEE_PERCENTAGE = parseFloat( | ||
| process.env.BYOK_FEE_PERCENTAGE ?? "0.05", | ||
| ); |
There was a problem hiding this comment.
BYOK_FEE_PERCENTAGE is parsed directly from process.env without validation. If the env var is missing/empty/invalid, parseFloat can yield NaN, and if it’s set to an out-of-range value (e.g. 5 instead of 0.05) the worker will over/under-charge. Consider sanitizing/clamping (e.g. default to 0.05 when Number.isFinite fails, and enforce a 0–1 range).
| export const BYOK_FEE_PERCENTAGE = parseFloat( | |
| process.env.BYOK_FEE_PERCENTAGE ?? "0.05", | |
| ); | |
| const rawByokFee = process.env.BYOK_FEE_PERCENTAGE; | |
| let parsedByokFee = rawByokFee != null && rawByokFee.trim() !== "" ? Number(rawByokFee) : NaN; | |
| if (!Number.isFinite(parsedByokFee)) { | |
| parsedByokFee = 0.05; // default to 5% if invalid/missing | |
| } | |
| // Clamp to [0, 1] to avoid extreme over/under-charging | |
| export const BYOK_FEE_PERCENTAGE = Math.max(0, Math.min(1, parsedByokFee)); |
| if (row.cost) { | ||
| const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE); | ||
| totalToDeduct = totalToDeduct.plus(byokFee); | ||
| } |
There was a problem hiding this comment.
Inside the api-keys branch, if (row.cost) is redundant because this whole block is already guarded by if (row.cost && row.cost > 0 && !row.cached). Removing the inner check (or moving BYOK fee computation up) would simplify the control flow and reduce the chance of inconsistent conditions later.
| if (row.cost) { | |
| const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE); | |
| totalToDeduct = totalToDeduct.plus(byokFee); | |
| } | |
| const byokFee = new Decimal(row.cost).times(BYOK_FEE_PERCENTAGE); | |
| totalToDeduct = totalToDeduct.plus(byokFee); |
| @@ -176,12 +179,12 @@ describe("Log Processing", () => { | |||
| // Process the logs | |||
| await batchProcessLogs(); | |||
|
|
|||
| // Verify no credits were deducted for api-keys mode | |||
| // Verify only BYOK fee was deducted (not full cost) | |||
| const updatedOrg = await db.query.organization.findFirst({ | |||
| where: { id: { eq: testOrg.id } }, | |||
| }); | |||
|
|
|||
| expect(Number(updatedOrg!.credits)).toBe(initialCredits); | |||
| expect(Number(updatedOrg!.credits)).toBe(initialCredits - expectedFee); | |||
| }); | |||
There was a problem hiding this comment.
This assertion compares floating point arithmetic exactly (toBe(initialCredits - expectedFee)), which is brittle for values like 0.01 * 0.05. Use a decimal-safe comparison (e.g., toBeCloseTo) or compute/compare using Decimal to avoid flaky failures across runtimes/DB numeric conversions.
| test("should deduct only BYOK fee (5%) for api-keys mode logs", async () => { | ||
| const initialCredits = Number(testOrg.credits); | ||
| const cost = 0.01; | ||
| const byokFeePercentage = 0.05; // 5% |
There was a problem hiding this comment.
The test hardcodes 0.05 instead of asserting against the actual configured BYOK_FEE_PERCENTAGE behavior. Since the PR makes this configurable via env var, consider setting process.env.BYOK_FEE_PERCENTAGE in the test (with module reset) and/or importing the constant so the test covers the override semantics and won’t drift if the default changes.
| const byokFeePercentage = 0.05; // 5% | |
| process.env.BYOK_FEE_PERCENTAGE = "0.05"; | |
| const byokFeePercentage = Number(process.env.BYOK_FEE_PERCENTAGE); |
Summary
api-keysmode), 5% of the tracked request cost is deducted from their organization creditsBYOK_FEE_PERCENTAGEenvironment variable (default: 0.05)Changes
packages/shared/src/fees.ts— RestoredBYOK_FEE_PERCENTAGEexport (default 0.05)apps/worker/src/worker.ts— Restored BYOK fee charging logic in batch log processing for api-keys modeapps/worker/src/log-processing.spec.ts— Updated test to expect 5% BYOK fee deduction.env.example— AddedBYOK_FEE_PERCENTAGE=0.05configurationTest plan
BYOK_FEE_PERCENTAGEenv var overrides the default🤖 Generated with Claude Code
Summary by CodeRabbit
Documentation
Chores