Skip to content

Conversation

@basnijholt
Copy link
Contributor

@basnijholt basnijholt commented Dec 8, 2025

Disclaimer: made with Claude but human verified.

Summary

Add support for anthropic.claude- and anthropic/claude- prefixed models in the isClaudeModel filter.

Problem

LiteLLM lists Opus 4.5 models with anthropic.claude- prefix (e.g., anthropic.claude-opus-4-5-20251101-v1:0) but the isClaudeModel filter only kept models starting with claude-, causing pricing lookups to fail for Opus 4.5.

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Walkthrough

Broadened model-name detection in apps/ccusage/src/_macro.ts: isClaudeModel now returns true for names starting with claude-, anthropic.claude-, or anthropic/claude-. No other functional changes were made.

Changes

Cohort / File(s) Summary
Model-detection update
apps/ccusage/src/_macro.ts
Expanded isClaudeModel prefix checks to match claude-, anthropic.claude-, and anthropic/claude-. No export or other behavioral changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify the prefix-check logic covers the three forms and has no false positives.
  • Run any existing tests that rely on model detection to ensure no regressions.

Suggested labels

bug

Poem

🐰 I sniffed the names from near and far,
Dot, slash, or dash — I know what they are.
A small tweak done, no fuss, no fight,
Now Claude models all pop into sight! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding support for Bedrock-prefixed model names (anthropic.claude- and anthropic/claude-) to fix Opus 4.5 pricing detection.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/ccusage/src/_macro.ts (1)

15-39: In-source tests are good; consider also asserting the canonical Opus 4 model name

The vitest block follows the in-source testing pattern and validates all three supported prefixes plus negative cases, which is exactly what we want for this helper. To stay aligned with the CLAUDE.md guidance that tests should use the current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514) and to keep explicit coverage for the canonical Opus 4 name alongside Opus 4.5, you could add one more assertion:

 		it('matches claude- prefixed models', () => {
 			expect(isClaudeModel('claude-sonnet-4-20250514', mockPricing)).toBe(true);
-			expect(isClaudeModel('claude-opus-4-5-20251101', mockPricing)).toBe(true);
+			expect(isClaudeModel('claude-opus-4-20250514', mockPricing)).toBe(true);
+			expect(isClaudeModel('claude-opus-4-5-20251101', mockPricing)).toBe(true);
 		});

This keeps the new Opus 4.5 coverage while also asserting the canonical Opus 4 model name mentioned in the CLAUDE docs. Based on learnings, this keeps tests in sync with our documented model naming expectations.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fed61e5 and fd45293.

📒 Files selected for processing (1)
  • apps/ccusage/src/_macro.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/ccusage/src/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/src/**/*.ts: Write tests in-source using if (import.meta.vitest != null) blocks instead of separate test files
Use Vitest globals (describe, it, expect) without imports in test blocks
In tests, use current Claude 4 models (sonnet-4, opus-4)
Use fs-fixture with createFixture() to simulate Claude data in tests
Only export symbols that are actually used by other modules
Do not use console.log; use the logger utilities from src/logger.ts instead

Files:

  • apps/ccusage/src/_macro.ts
apps/ccusage/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/**/*.ts: NEVER use await import() dynamic imports anywhere (especially in tests)
Prefer @praha/byethrow Result type for error handling instead of try-catch
Use .ts extensions for local imports (e.g., import { foo } from './utils.ts')

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use ESLint for linting and formatting with tab indentation and double quotes
No console.log allowed except where explicitly disabled with eslint-disable; use logger.ts instead
Use file paths with Node.js path utilities for cross-platform compatibility
Use variables starting with lowercase (camelCase) for variable names
Can use UPPER_SNAKE_CASE for constants

Files:

  • apps/ccusage/src/_macro.ts
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript with strict mode and bundler module resolution

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() for wrapping operations that may throw (JSON parsing, etc.)
Use Result.isFailure() for checking errors (more readable than !Result.isSuccess())
Use early return pattern (if (Result.isFailure(result)) continue;) instead of ternary operators when checking Results
Keep traditional try-catch only for file I/O with complex error handling or legacy code that's hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for better code clarity
Use uppercase (PascalCase) for type names
Only export constants, functions, and types that are actually used by other modules - internal constants used only within the same file should NOT be exported
In-source testing pattern: write tests directly in source files using if (import.meta.vitest != null) blocks
CRITICAL: DO NOT use await import() dynamic imports anywhere in the codebase - this causes tree-shaking issues
CRITICAL: Never use dynamic imports with await import() in vitest test blocks - this is particularly problematic for test execution
Vitest globals (describe, it, expect) are enabled and available without imports since globals are configured
Create mock data using fs-fixture with createFixture() for Claude data directory simulation in tests
All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Model names in tests must exactly match LiteLLM's pricing database entries

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Claude model naming convention: claude-{model-type}-{generation}-{date} (e.g., claude-sonnet-4-20250514, NOT claude-4-sonnet-20250514)

Files:

  • apps/ccusage/src/_macro.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Write tests in-source using `if (import.meta.vitest != null)` blocks instead of separate test files
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Create mock data using `fs-fixture` with `createFixture()` for Claude data directory simulation in tests
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/*.ts : Use `.ts` extensions for local imports (e.g., `import { foo } from './utils.ts'`)
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Fetch per-model pricing from LiteLLM model_prices_and_context_window.json via LiteLLMPricingFetcher using an offline cache scoped to Codex-prefixed models; handle aliases (e.g., gpt-5-codex → gpt-5) in CodexPricingSource

Applied to files:

  • apps/ccusage/src/_macro.ts
🧬 Code graph analysis (1)
apps/ccusage/src/_macro.ts (1)
packages/internal/src/pricing.ts (1)
  • LiteLLMModelPricing (49-49)
🔇 Additional comments (1)
apps/ccusage/src/_macro.ts (1)

9-13: Prefix-based Claude model detection looks correct and minimal

The expanded isClaudeModel implementation cleanly covers the three expected Claude prefixes (claude-, anthropic.claude-, anthropic/claude-) without introducing extra coupling to pricing details. Keeping _pricing unused here is reasonable since the function is used as a simple predicate for filterPricingDataset and matches the expected callback shape.

No changes requested.

LiteLLM lists Opus 4.5 models with anthropic.claude- prefix
(e.g., anthropic.claude-opus-4-5-20251101-v1:0) but the
isClaudeModel filter only kept models starting with claude-.

This adds support for anthropic.claude- and anthropic/claude-
prefixes to include Bedrock-format models in the pricing dataset.
@basnijholt basnijholt force-pushed the fix/opus-4-5-pricing branch from fd45293 to 36734a2 Compare December 8, 2025 17:15
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/ccusage/src/_macro.ts (1)

9-13: Prefix detection correctly extended; consider whether export is needed

The broadened isClaudeModel logic cleanly covers claude-, anthropic.claude- (Bedrock), and anthropic/claude- prefixes and fits the filterPricingDataset usage well. If no other modules consume this helper yet, you could keep it non-exported to avoid expanding the public surface, but the implementation itself looks good as-is.

As per coding guidelines, only export symbols that are actually used by other modules.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd45293 and 36734a2.

📒 Files selected for processing (1)
  • apps/ccusage/src/_macro.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/ccusage/src/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/src/**/*.ts: Write tests in-source using if (import.meta.vitest != null) blocks instead of separate test files
Use Vitest globals (describe, it, expect) without imports in test blocks
In tests, use current Claude 4 models (sonnet-4, opus-4)
Use fs-fixture with createFixture() to simulate Claude data in tests
Only export symbols that are actually used by other modules
Do not use console.log; use the logger utilities from src/logger.ts instead

Files:

  • apps/ccusage/src/_macro.ts
apps/ccusage/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/**/*.ts: NEVER use await import() dynamic imports anywhere (especially in tests)
Prefer @praha/byethrow Result type for error handling instead of try-catch
Use .ts extensions for local imports (e.g., import { foo } from './utils.ts')

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use ESLint for linting and formatting with tab indentation and double quotes
No console.log allowed except where explicitly disabled with eslint-disable; use logger.ts instead
Use file paths with Node.js path utilities for cross-platform compatibility
Use variables starting with lowercase (camelCase) for variable names
Can use UPPER_SNAKE_CASE for constants

Files:

  • apps/ccusage/src/_macro.ts
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript with strict mode and bundler module resolution

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() for wrapping operations that may throw (JSON parsing, etc.)
Use Result.isFailure() for checking errors (more readable than !Result.isSuccess())
Use early return pattern (if (Result.isFailure(result)) continue;) instead of ternary operators when checking Results
Keep traditional try-catch only for file I/O with complex error handling or legacy code that's hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for better code clarity
Use uppercase (PascalCase) for type names
Only export constants, functions, and types that are actually used by other modules - internal constants used only within the same file should NOT be exported
In-source testing pattern: write tests directly in source files using if (import.meta.vitest != null) blocks
CRITICAL: DO NOT use await import() dynamic imports anywhere in the codebase - this causes tree-shaking issues
CRITICAL: Never use dynamic imports with await import() in vitest test blocks - this is particularly problematic for test execution
Vitest globals (describe, it, expect) are enabled and available without imports since globals are configured
Create mock data using fs-fixture with createFixture() for Claude data directory simulation in tests
All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Model names in tests must exactly match LiteLLM's pricing database entries

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Claude model naming convention: claude-{model-type}-{generation}-{date} (e.g., claude-sonnet-4-20250514, NOT claude-4-sonnet-20250514)

Files:

  • apps/ccusage/src/_macro.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Write tests in-source using `if (import.meta.vitest != null)` blocks instead of separate test files
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use Vitest globals (`describe`, `it`, `expect`) without imports in test blocks
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/*.{test,spec}.ts : Vitest globals enabled: use `describe`, `it`, `expect` directly without importing them
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : In-source testing pattern: write tests directly in source files using `if (import.meta.vitest != null)` blocks
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Fetch per-model pricing from LiteLLM model_prices_and_context_window.json via LiteLLMPricingFetcher using an offline cache scoped to Codex-prefixed models; handle aliases (e.g., gpt-5-codex → gpt-5) in CodexPricingSource

Applied to files:

  • apps/ccusage/src/_macro.ts
🧬 Code graph analysis (1)
apps/ccusage/src/_macro.ts (1)
packages/internal/src/pricing.ts (1)
  • LiteLLMModelPricing (49-49)
🔇 Additional comments (1)
apps/ccusage/src/_macro.ts (1)

15-37: In-source tests nicely cover all prefixes and negative cases

The import.meta.vitest guard plus direct use of describe/it/expect matches the in-source testing pattern, and the cases exercise all three supported prefixes plus non-Claude models. The use of current Claude 4 family names (Sonnet 4, Opus 4.5) also aligns with the CLAUDE model guidance. No changes needed here.

Based on learnings, this follows the recommended in-source Vitest style and current Claude 4 model naming.

Copy link

@coderabbitai coderabbitai bot left a comment

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 (1)
apps/ccusage/src/_macro.ts (1)

25-25: Replace console.warn with logger utility.

The coding guidelines prohibit console.log and console.warn usage. Use the logger utilities from src/logger.ts instead.

As per coding guidelines, replace console.warn with the appropriate logger function:

-		console.warn('Failed to prefetch Claude pricing data, proceeding with empty cache.', error);
+		// Import logger at the top of the file
+		logger.warn('Failed to prefetch Claude pricing data, proceeding with empty cache.', error);

You'll need to add the logger import at the top:

import { logger } from './logger.ts';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36734a2 and 67e9350.

📒 Files selected for processing (1)
  • apps/ccusage/src/_macro.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/ccusage/src/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/src/**/*.ts: Write tests in-source using if (import.meta.vitest != null) blocks instead of separate test files
Use Vitest globals (describe, it, expect) without imports in test blocks
In tests, use current Claude 4 models (sonnet-4, opus-4)
Use fs-fixture with createFixture() to simulate Claude data in tests
Only export symbols that are actually used by other modules
Do not use console.log; use the logger utilities from src/logger.ts instead

Files:

  • apps/ccusage/src/_macro.ts
apps/ccusage/**/*.ts

📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)

apps/ccusage/**/*.ts: NEVER use await import() dynamic imports anywhere (especially in tests)
Prefer @praha/byethrow Result type for error handling instead of try-catch
Use .ts extensions for local imports (e.g., import { foo } from './utils.ts')

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use ESLint for linting and formatting with tab indentation and double quotes
No console.log allowed except where explicitly disabled with eslint-disable; use logger.ts instead
Use file paths with Node.js path utilities for cross-platform compatibility
Use variables starting with lowercase (camelCase) for variable names
Can use UPPER_SNAKE_CASE for constants

Files:

  • apps/ccusage/src/_macro.ts
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript with strict mode and bundler module resolution

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() for wrapping operations that may throw (JSON parsing, etc.)
Use Result.isFailure() for checking errors (more readable than !Result.isSuccess())
Use early return pattern (if (Result.isFailure(result)) continue;) instead of ternary operators when checking Results
Keep traditional try-catch only for file I/O with complex error handling or legacy code that's hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for better code clarity
Use uppercase (PascalCase) for type names
Only export constants, functions, and types that are actually used by other modules - internal constants used only within the same file should NOT be exported
In-source testing pattern: write tests directly in source files using if (import.meta.vitest != null) blocks
CRITICAL: DO NOT use await import() dynamic imports anywhere in the codebase - this causes tree-shaking issues
CRITICAL: Never use dynamic imports with await import() in vitest test blocks - this is particularly problematic for test execution
Vitest globals (describe, it, expect) are enabled and available without imports since globals are configured
Create mock data using fs-fixture with createFixture() for Claude data directory simulation in tests
All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Model names in tests must exactly match LiteLLM's pricing database entries

Files:

  • apps/ccusage/src/_macro.ts
**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Claude model naming convention: claude-{model-type}-{generation}-{date} (e.g., claude-sonnet-4-20250514, NOT claude-4-sonnet-20250514)

Files:

  • apps/ccusage/src/_macro.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/*.ts : Use `.ts` extensions for local imports (e.g., `import { foo } from './utils.ts'`)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Fetch per-model pricing from LiteLLM model_prices_and_context_window.json via LiteLLMPricingFetcher using an offline cache scoped to Codex-prefixed models; handle aliases (e.g., gpt-5-codex → gpt-5) in CodexPricingSource

Applied to files:

  • apps/ccusage/src/_macro.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries

Applied to files:

  • apps/ccusage/src/_macro.ts
🔇 Additional comments (1)
apps/ccusage/src/_macro.ts (1)

10-12: Verify the anthropic/claude- prefix pattern against LiteLLM's pricing database.

The anthropic.claude- prefix is confirmed by AWS Bedrock documentation, but the anthropic/claude- variant with a forward slash is not documented in official Bedrock sources. Ensure this pattern is actually used in LiteLLM before merging.

Additionally, the PR claims 4 unit tests were added for isClaudeModel, but coding guidelines for apps/ccusage/src/**/*.ts require in-source tests using if (import.meta.vitest != null) blocks. Verify tests are present and properly located in the source file. Also check that console.warn on line 25 (if present) is replaced with logger utilities from src/logger.ts per coding guidelines.

Comment on lines 9 to 13
function isClaudeModel(modelName: string, _pricing: LiteLLMModelPricing): boolean {
return modelName.startsWith('claude-');
return modelName.startsWith('claude-')
|| modelName.startsWith('anthropic.claude-')
|| modelName.startsWith('anthropic/claude-');
}
Copy link

@coderabbitai coderabbitai bot Dec 8, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add in-source unit tests for the expanded prefix patterns.

The PR summary mentions 4 unit tests were added for isClaudeModel, but they're not present in this file. According to coding guidelines, tests should be written in-source using if (import.meta.vitest != null) blocks.

Add a test block at the end of the file:

+
+if (import.meta.vitest != null) {
+	const { describe, it, expect } = import.meta.vitest;
+
+	describe("isClaudeModel", () => {
+		const mockPricing = {} as LiteLLMModelPricing;
+
+		it("should match standard claude- prefix", () => {
+			expect(isClaudeModel("claude-sonnet-4-20250514", mockPricing)).toBe(true);
+		});
+
+		it("should match anthropic.claude- prefix (Bedrock)", () => {
+			expect(isClaudeModel("anthropic.claude-opus-4-5-20251101-v1:0", mockPricing)).toBe(true);
+		});
+
+		it("should match anthropic/claude- prefix (Bedrock)", () => {
+			expect(isClaudeModel("anthropic/claude-sonnet-4-20250514", mockPricing)).toBe(true);
+		});
+
+		it("should not match non-Claude models", () => {
+			expect(isClaudeModel("gpt-4", mockPricing)).toBe(false);
+			expect(isClaudeModel("claude", mockPricing)).toBe(false);
+		});
+	});
+}

Note: Based on coding guidelines, Vitest globals are enabled, so you can use describe, it, expect without imports.

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had these kinds of tests before, but I removed them because this function is so trivial and would just be noise.

Copy link

Choose a reason for hiding this comment

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

@basnijholt, understood! I respect your judgment that the function is straightforward enough that tests would add more noise than value. The logic is indeed simple—three prefix checks—and you've already validated it works with your Opus 4.5 use case.


🧠 Learnings used
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Write tests in-source using `if (import.meta.vitest != null)` blocks instead of separate test files

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : In-source testing pattern: write tests directly in source files using `if (import.meta.vitest != null)` blocks

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: When adding new model tests, verify the model exists in LiteLLM before implementation

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use Vitest globals (`describe`, `it`, `expect`) without imports in test blocks

Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance

Copy link
Owner

@ryoppippi ryoppippi left a comment

Choose a reason for hiding this comment

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

LGTM

@ryoppippi ryoppippi merged commit c300bf4 into ryoppippi:main Dec 8, 2025
3 checks passed
@ryoppippi
Copy link
Owner

thanks @basnijholt !!!!!!!!!!1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants