-
-
Notifications
You must be signed in to change notification settings - Fork 317
feat(ccusage): add GLM-4.5 model support and pricing configuration #657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add deepinfra/ and vercel_ai_gateway/ to DEFAULT_PROVIDER_PREFIXES - Create GLM-specific prefetching logic in _glm-macro.ts - Update pricing fetcher to include GLM models alongside Claude models - Support GLM-4.5 and GLM-4.5-Air variants from LiteLLM database - Add comprehensive tests for GLM-4.5 model pricing - Fix cost calculation discrepancies for GLM-4.5 models Resolves issue where GLM-4.5 models fell back to pre-calculated costs instead of using dynamic pricing from LiteLLM database. Testing shows: - GLM-4.5 models now correctly match LiteLLM pricing data - Cost calculations are accurate with real LiteLLM prices - Implementation follows existing Claude/Codex patterns - No regression in existing functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Summary of ChangesHello @cobra91, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request integrates GLM-4.5 and GLM-4.5-Air models into the existing pricing system, ensuring their costs are accurately calculated by dynamically fetching pricing data from the LiteLLM database. It introduces new logic for GLM model identification and pricing prefetching, aligning with the architecture used for other supported models. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request effectively adds support for GLM-4.5 models and their pricing, including prefetching logic and updated provider configurations. The changes are well-structured and include relevant tests. My feedback focuses on a few areas to improve code clarity, type safety, and test conciseness. I've suggested simplifying a complex boolean expression in the GLM model detection logic, strengthening the type information in the pricing data combination function, and refactoring repetitive tests to be more maintainable.
- Simplify isGLMModel logic by removing redundant conditions - Improve type safety for combinePricingData return type - Parameterize GLM model tests using it.each for better maintainability - Remove unnecessary null assertion operators from test code 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
cobra91
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix gemini first review
apps/ccusage/src/_pricing-fetcher.ts
Outdated
| expect(cost).toBeGreaterThan(0); | ||
| }); | ||
|
|
||
| it.each([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use each test.
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. 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 |
|
@cobra91 could you fix them? |
commit: |
- Rename combinePricingData to prefetchCcusagePricing to avoid duplication - Revert it.each tests back to individual tests as requested by reviewer - Maintain simplified isGLMModel logic and improved type safety 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
|
@cobra91 i suspend gemini review bot. it is aweful |
|
fix lint error as well! |
… prefetchCcusagePricing.ts
Got error on codex need to fix too ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
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/_pricing-fetcher.ts (1)
51-61: Fix test model name and assert non-null pricing.The LiteLLM keys use anthopic/claude-4-... naming; current 'claude-sonnet-4-20250514' may not match. Also ensure pricing is non-null before use.
- const pricing = await Result.unwrap(fetcher.getModelPricing('claude-sonnet-4-20250514')); - const cost = fetcher.calculateCostFromPricing({ + const pricing = await Result.unwrap(fetcher.getModelPricing('anthropic/claude-4-sonnet-20250514')); + expect(pricing).not.toBeNull(); + const cost = fetcher.calculateCostFromPricing({ input_tokens: 1000, output_tokens: 500, cache_read_input_tokens: 300, - }, pricing); + }, pricing!);
🧹 Nitpick comments (2)
apps/ccusage/src/_macro.ts (1)
28-38: Tighten GLM prefix list to avoid accidental matches and keep it lowercased.Since matching is case-insensitive below, store prefixes lowercased and avoid overly broad items (e.g., 'glm-4' can match unintended variants). Prefer specific startsWith prefixes for known variants.
-const GLM_MODEL_PREFIXES = [ - 'glm-4', - 'glm-4.5', - 'glm-4-5', - 'deepinfra/zai-org/GLM', - 'vercel_ai_gateway/zai/glm', - 'deepinfra/glm', - 'vercel_ai_gateway/glm', - 'glm-4.5-air', - 'glm-4-air', -]; +const GLM_MODEL_PREFIXES = [ + 'glm-4.5', + 'glm-4-5', + 'glm-4.5-air', + 'deepinfra/zai-org/glm-4.5', + 'vercel_ai_gateway/zai/glm-4.5', +];apps/ccusage/src/_pricing-fetcher.ts (1)
63-85: Strengthen GLM tests with exact pricing assertions.Instead of cost > 0, assert expected rates to catch regressions. If you don’t want network in CI, add a tiny offline fallback for GLM-4.5 in prefetchGLMPricing on error/offline.
- const pricing = await Result.unwrap(fetcher.getModelPricing('glm-4.5')); - const cost = fetcher.calculateCostFromPricing({ + const pricing = await Result.unwrap(fetcher.getModelPricing('glm-4.5')); + expect(pricing).not.toBeNull(); + const cost = fetcher.calculateCostFromPricing({ input_tokens: 1000, output_tokens: 500, cache_read_input_tokens: 300, - }, pricing); - - expect(cost).toBeGreaterThan(0); + }, pricing!); + // Expect: input $0.60/M, output $2.20/M, cache-read $0.11/M + expect(cost).toBeCloseTo((1000 * 6e-7) + (500 * 2.2e-6) + (300 * 1.1e-7));Apply the same pattern for provider-prefixed and air variants (line 75-85 and 87-96).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/ccusage/src/_macro.ts(1 hunks)apps/ccusage/src/_pricing-fetcher.ts(2 hunks)packages/internal/src/pricing.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Use tab indentation and double quotes (ESLint formatting)
Do not use console.log; only allow where explicitly disabled via eslint-disable
Always use Node.js path utilities for file paths for cross-platform compatibility
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() to wrap operations that may throw (e.g., JSON parsing)
Use Result.isFailure() for checking errors instead of negating isSuccess()
Use early return on failures (e.g., if (Result.isFailure(r)) continue) instead of ternary patterns
For async operations, create a wrapper using Result.try() and call it
Keep traditional try-catch only for complex file I/O or legacy code that’s hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for clarity
Variables use camelCase naming
Types use PascalCase naming
Constants can use UPPER_SNAKE_CASE
Only export constants, functions, and types that are actually used by other modules
Do not export internal/private constants that are only used within the same file
Before exporting a constant, verify it is referenced by other modules
Use Vitest globals (describe, it, expect) without imports in test blocks
Never use await import() dynamic imports anywhere in the codebase
Never use dynamic imports inside Vitest test blocks
Use fs-fixture createFixture() for mock Claude data directories in tests
All tests must use current Claude 4 models (not Claude 3)
Test coverage should include both Sonnet and Opus models
Model names in tests must exactly match LiteLLM pricing database entries
Use logger.ts instead of console.log for logging
Files:
packages/internal/src/pricing.tsapps/ccusage/src/_macro.tsapps/ccusage/src/_pricing-fetcher.ts
apps/ccusage/src/**/*.ts
📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)
apps/ccusage/src/**/*.ts: Write tests in-source usingif (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)
Usefs-fixturewithcreateFixture()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 fromsrc/logger.tsinstead
Files:
apps/ccusage/src/_macro.tsapps/ccusage/src/_pricing-fetcher.ts
apps/ccusage/**/*.ts
📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)
apps/ccusage/**/*.ts: NEVER useawait import()dynamic imports anywhere (especially in tests)
Prefer@praha/byethrowResult type for error handling instead of try-catch
Use.tsextensions for local imports (e.g.,import { foo } from './utils.ts')
Files:
apps/ccusage/src/_macro.tsapps/ccusage/src/_pricing-fetcher.ts
**/_*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Internal files should use underscore prefix (e.g., _types.ts, _utils.ts, _consts.ts)
Files:
apps/ccusage/src/_macro.tsapps/ccusage/src/_pricing-fetcher.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
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
📚 Learning: 2025-09-18T16:07:16.277Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
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.tsapps/ccusage/src/_pricing-fetcher.ts
📚 Learning: 2025-09-18T17:43:09.223Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-18T17:43:09.223Z
Learning: Applies to **/*.ts : Model names in tests must exactly match LiteLLM pricing database entries
Applied to files:
apps/ccusage/src/_pricing-fetcher.ts
📚 Learning: 2025-09-18T16:07:16.277Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
Learning: Cost calculation per model/date: charge non-cached input, cached input (fallback to input rate if missing), and output using the specified per-million token rates
Applied to files:
apps/ccusage/src/_pricing-fetcher.ts
🧬 Code graph analysis (2)
apps/ccusage/src/_macro.ts (2)
packages/internal/src/pricing.ts (1)
LiteLLMModelPricing(49-49)packages/internal/src/pricing-fetch-utils.ts (3)
createPricingDataset(11-13)fetchLiteLLMPricingDataset(15-38)filterPricingDataset(40-51)
apps/ccusage/src/_pricing-fetcher.ts (2)
apps/ccusage/src/_macro.ts (2)
prefetchClaudePricing(13-26)prefetchGLMPricing(47-60)packages/internal/src/pricing.ts (2)
LiteLLMModelPricing(49-49)LiteLLMPricingFetcher(91-357)
🔇 Additional comments (3)
apps/ccusage/src/_pricing-fetcher.ts (2)
4-4: Macro import is fine; ensure macro tooling handles type: 'macro' attribute.No action if your toolchain already supports it; otherwise gate behind build-flag.
7-15: Provider prefixes update — approved; no zhipuai present.
Verified BerriAI/litellm model_prices_and_context_window.json: no keys/prefixes matching "zhipu" or "zhipuai" were found, so no change required.packages/internal/src/pricing.ts (1)
74-76: GLM coverage verified — no zhipuai entries foundLiteLLM's model_prices_and_context_window.json exposes GLM models under deepinfra/, fireworks_ai/, together_ai/, and vercel_ai_gateway/; no zhipuai/ (or similar) keys were found, so the added deepinfra/ and vercel_ai_gateway/ prefixes are sufficient.
Rabbit seem very good, it's the same thing like on roo code GitHub who self fix a lot of issue ? 🤔 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/codex/src/commands/daily.ts (1)
40-41: Preserve error details; log stack at debug level.Only logging
messagehides the stack and error name. Suggest logging a concise error line and pushing the stack to debug for diagnostics.- logger.error(error instanceof Error ? error.message : String(error)); + const msg = error instanceof Error ? `${error.name}: ${error.message}` : String(error); + logger.error(msg); + if (error instanceof Error && error.stack) { + logger.debug(error.stack); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
AGENTS.md(1 hunks)README.md(1 hunks)apps/ccusage/AGENTS.md(1 hunks)apps/ccusage/eslint.config.js(1 hunks)apps/ccusage/src/_pricing-fetcher.ts(2 hunks)apps/codex/AGENTS.md(1 hunks)apps/codex/eslint.config.js(1 hunks)apps/codex/src/commands/daily.ts(1 hunks)apps/mcp/AGENTS.md(1 hunks)apps/mcp/eslint.config.js(1 hunks)docs/AGENTS.md(1 hunks)packages/internal/AGENTS.md(1 hunks)packages/terminal/AGENTS.md(1 hunks)
✅ Files skipped from review due to trivial changes (9)
- apps/ccusage/AGENTS.md
- README.md
- packages/internal/AGENTS.md
- docs/AGENTS.md
- AGENTS.md
- apps/codex/AGENTS.md
- apps/mcp/AGENTS.md
- packages/terminal/AGENTS.md
- apps/ccusage/eslint.config.js
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Use tab indentation and double quotes (ESLint formatting)
Do not use console.log; only allow where explicitly disabled via eslint-disable
Always use Node.js path utilities for file paths for cross-platform compatibility
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() to wrap operations that may throw (e.g., JSON parsing)
Use Result.isFailure() for checking errors instead of negating isSuccess()
Use early return on failures (e.g., if (Result.isFailure(r)) continue) instead of ternary patterns
For async operations, create a wrapper using Result.try() and call it
Keep traditional try-catch only for complex file I/O or legacy code that’s hard to refactor
Always use Result.isFailure() and Result.isSuccess() type guards for clarity
Variables use camelCase naming
Types use PascalCase naming
Constants can use UPPER_SNAKE_CASE
Only export constants, functions, and types that are actually used by other modules
Do not export internal/private constants that are only used within the same file
Before exporting a constant, verify it is referenced by other modules
Use Vitest globals (describe, it, expect) without imports in test blocks
Never use await import() dynamic imports anywhere in the codebase
Never use dynamic imports inside Vitest test blocks
Use fs-fixture createFixture() for mock Claude data directories in tests
All tests must use current Claude 4 models (not Claude 3)
Test coverage should include both Sonnet and Opus models
Model names in tests must exactly match LiteLLM pricing database entries
Use logger.ts instead of console.log for logging
Files:
apps/codex/src/commands/daily.tsapps/ccusage/src/_pricing-fetcher.ts
apps/ccusage/src/**/*.ts
📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)
apps/ccusage/src/**/*.ts: Write tests in-source usingif (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)
Usefs-fixturewithcreateFixture()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 fromsrc/logger.tsinstead
Files:
apps/ccusage/src/_pricing-fetcher.ts
apps/ccusage/**/*.ts
📄 CodeRabbit inference engine (apps/ccusage/CLAUDE.md)
apps/ccusage/**/*.ts: NEVER useawait import()dynamic imports anywhere (especially in tests)
Prefer@praha/byethrowResult type for error handling instead of try-catch
Use.tsextensions for local imports (e.g.,import { foo } from './utils.ts')
Files:
apps/ccusage/src/_pricing-fetcher.ts
**/_*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Internal files should use underscore prefix (e.g., _types.ts, _utils.ts, _consts.ts)
Files:
apps/ccusage/src/_pricing-fetcher.ts
🧠 Learnings (6)
📚 Learning: 2025-09-18T17:43:09.223Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-18T17:43:09.223Z
Learning: Applies to **/*.test.@(ts|tsx) : Do not create separate test files; tests should be in-source via if (import.meta.vitest != null) blocks
Applied to files:
apps/mcp/eslint.config.jsapps/codex/eslint.config.js
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
PR: ryoppippi/ccusage#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
Applied to files:
apps/mcp/eslint.config.jsapps/codex/eslint.config.js
📚 Learning: 2025-09-18T16:07:16.277Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
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/_pricing-fetcher.ts
📚 Learning: 2025-09-18T17:43:09.223Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-18T17:43:09.223Z
Learning: Applies to **/*.ts : Model names in tests must exactly match LiteLLM pricing database entries
Applied to files:
apps/ccusage/src/_pricing-fetcher.ts
📚 Learning: 2025-09-18T16:07:16.277Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
Learning: Pricing tests must inject stub offline loaders to avoid network access
Applied to files:
apps/ccusage/src/_pricing-fetcher.ts
📚 Learning: 2025-09-18T16:07:16.277Z
Learnt from: CR
PR: ryoppippi/ccusage#0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.277Z
Learning: Cost calculation per model/date: charge non-cached input, cached input (fallback to input rate if missing), and output using the specified per-million token rates
Applied to files:
apps/ccusage/src/_pricing-fetcher.ts
🧬 Code graph analysis (2)
apps/codex/src/commands/daily.ts (1)
apps/codex/src/logger.ts (1)
logger(5-5)
apps/ccusage/src/_pricing-fetcher.ts (2)
apps/ccusage/src/_macro.ts (2)
prefetchClaudePricing(13-26)prefetchGLMPricing(47-60)packages/internal/src/pricing.ts (2)
LiteLLMModelPricing(49-49)LiteLLMPricingFetcher(91-357)
🔇 Additional comments (9)
apps/ccusage/src/_pricing-fetcher.ts (9)
1-1: Good: Narrow typing for merged pricing map.Importing
LiteLLMModelPricingimproves type safety for the merged dataset.
4-4: Macro import LGTM.Adding
prefetchGLMPricingintegrates GLM pricing into the local fetcher.
7-15: Provider prefixes update looks correct.Adding
deepinfra/andvercel_ai_gateway/aligns with the issue and LiteLLM variants. Please verify exact casing/slug matches the LiteLLM keys in your cache to avoid misses.
38-39: Switch to updated prefixes constant: LGTM.Using
CCUSAGE_PROVIDER_PREFIXESensures the new providers are matched.
54-62: Claude cost calc test: OK.Asserts presence and basic cost > 0. Consider adding an Opus model test elsewhere to satisfy coverage guidance.
64-75: GLM-4.5 cost calc test: OK.Covers the base GLM-4.5 name path.
77-88: GLM-4.5 with provider prefix: OK.Validates the new provider prefixes are effective.
90-101: GLM-4.5-Air variant: OK.Covers the Air variant; basic assertions look fine.
17-30: Avoid import-time network; defer prefetch and honor offline flag.
PREFETCHED_*triggers fetch at module import, ignoring theofflinector flag and causing network in offline/tests. Defer the calls and threadofflinethroughofflineLoader.Apply this diff:
-const PREFETCHED_CLAUDE_PRICING = prefetchClaudePricing(); -const PREFETCHED_GLM_PRICING = prefetchGLMPricing(); +// Defer prefetch until explicitly invoked to honor offline mode and avoid module‑import side effects. -async function prefetchCcusagePricing(): Promise<Record<string, LiteLLMModelPricing>> { - const [claudePricing, glmPricing] = await Promise.all([ - PREFETCHED_CLAUDE_PRICING, - PREFETCHED_GLM_PRICING, - ]); - - return { - ...claudePricing, - ...glmPricing, - }; -} +async function prefetchCcusagePricing(opts?: { offline?: boolean }): Promise<Record<string, LiteLLMModelPricing>> { + const prevOffline = process.env.OFFLINE; + try { + if (opts?.offline === true) { + process.env.OFFLINE = 'true'; + } + const [claudePricing, glmPricing] = await Promise.all([ + prefetchClaudePricing(), + prefetchGLMPricing(), + ]); + return { ...claudePricing, ...glmPricing }; + } + finally { + process.env.OFFLINE = prevOffline; + } +}And pass the offline intent to the loader:
- offlineLoader: async () => prefetchCcusagePricing(), + offlineLoader: async () => prefetchCcusagePricing({ offline: true }),Also applies to: 36-36
| ignores: [ | ||
| 'packages', | ||
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Fix Flat Config ignore path: current pattern won’t ignore monorepo root “packages/”.
In Flat Config, patterns are resolved relative to this config file’s directory (apps/codex). 'packages' targets apps/codex/packages, not ../../packages. Use a parent‑relative glob so CI actually skips the workspace packages.
Apply this diff:
- ignores: [
- 'packages',
- ],
+ ignores: [
+ '../../packages/**',
+ ],Optionally, make it explicit by prepending a top-level ignore object instead of passing through ryoppippi():
-import { ryoppippi } from '@ryoppippi/eslint-config';
+import { ryoppippi } from '@ryoppippi/eslint-config';
/** @type {import('eslint').Linter.FlatConfig[]} */
-const config = ryoppippi({
+const base = ryoppippi({
type: 'app',
- ignores: [
- 'packages',
- ],
}, {
rules: {
'test/no-importing-vitest-globals': 'error',
},
});
-export default config;
+export default [
+ { ignores: ['../../packages/**'] },
+ ...base,
+];Run to verify the packages workspace is linted elsewhere (or decide not to ignore it here if it isn’t):
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "ESLint configs found under packages/:"
fd -HI --max-depth 3 'eslint.config.*' packages || trueLength of output: 107
Fix Flat Config ignore: use parent-relative glob to skip monorepo packages/
Flat Config resolves patterns relative to apps/codex; 'packages' matches apps/codex/packages and will not ignore the repo root packages/ (verified: packages/internal/eslint.config.js, packages/terminal/eslint.config.js).
File: apps/codex/eslint.config.js (lines 6–8)
Apply this diff:
- ignores: [
- 'packages',
- ],
+ ignores: [
+ '../../packages/**',
+ ],Optionally, make it explicit by prepending a top-level ignore object instead of passing through ryoppippi():
-import { ryoppippi } from '@ryoppippi/eslint-config';
+import { ryoppippi } from '@ryoppippi/eslint-config';
/** @type {import('eslint').Linter.FlatConfig[]} */
-const config = ryoppippi({
+const base = ryoppippi({
type: 'app',
- ignores: [
- 'packages',
- ],
}, {
rules: {
'test/no-importing-vitest-globals': 'error',
},
});
-export default config;
+export default [
+ { ignores: ['../../packages/**'] },
+ ...base,
+];📝 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.
| ignores: [ | |
| 'packages', | |
| ], | |
| ignores: [ | |
| '../../packages/**', | |
| ], |
🤖 Prompt for AI Agents
In apps/codex/eslint.config.js around lines 6–8, the ignore pattern 'packages'
is resolved relative to apps/codex and therefore does not exclude the repo-root
packages/; replace that entry with a parent-relative glob like
'../../packages/**' so it matches the monorepo packages directory, or
alternatively add an explicit top-level ignore object (e.g. ignore:
['../../packages/**']) instead of passing the pattern through ryoppippi() to
ensure the root packages are skipped.
| ignores: [ | ||
| 'packages', | ||
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Same path issue: adjust ignore to target the root “packages/”.
'packages' won’t match the sibling workspace from apps/mcp. Use a parent‑relative glob.
Apply this diff:
- ignores: [
- 'packages',
- ],
+ ignores: [
+ '../../packages/**',
+ ],If you prefer a robust shape, prepend a top-level ignore object and spread the shared config (same pattern as suggested in apps/codex).
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "ESLint configs found under packages/:"
fd -HI --max-depth 3 'eslint.config.*' packages || trueLength of output: 107
Adjust ESLint ignore to target the top-level packages/
Replace the local 'packages' ignore (relative to apps/mcp) with a parent-relative glob so it matches the repo root packages/.
File: apps/mcp/eslint.config.js Lines: 6-8
- ignores: [
- 'packages',
- ],
+ ignores: [
+ '../../packages/**',
+ ],📝 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.
| ignores: [ | |
| 'packages', | |
| ], | |
| ignores: [ | |
| '../../packages/**', | |
| ], |
🤖 Prompt for AI Agents
In apps/mcp/eslint.config.js around lines 6 to 8, the ignores array currently
uses a local 'packages' entry which only excludes apps/mcp/packages; change it
to exclude the repository root packages/ by replacing the entry with a
parent-relative glob like '../../packages' or a repo-root glob 'packages/**'
depending on how ESLint resolves paths in your setup; update the ignores array
to use the correct glob so ESLint skips the top-level packages directory.
|
@cobra91 hey, i'm thinking about this pr. do we need this? because if you use ccusage without offline mode it must works. for example some users used qwen with ccusage and they can track it so well. doesn't the current ccusage work with GLM-4.5 in online mode? |
That work for qwen3 because your dependency have it |
|
@cobra91 I think we need to refresh the litellm cache. |
|
https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json |
| 'deepinfra/', | ||
| 'vercel_ai_gateway/', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and now deepinfra and vercel is included. should not included in this one PR..
|
so please check again |
|
oh i mistakenly approved. i'll revert it so i'd love to create a different PR again. |
|
and i think we cannot reproduce it. |
|
so probably i close this. |
I don't contribute to litellm for the moment and npx ccusage fetch from litellm |
Like u see on my screenshot the price calculated and real are really different no ? Or maybe I make a mistake? |
|
@cobra91 I'll take a look at it |
little late no ? |



Summary
Problem Resolved
This resolves issue #656 where GLM-4.5 models fell back to pre-calculated costs instead of using dynamic pricing from LiteLLM database.
Testing Results
Files Changed
packages/internal/src/pricing.ts- Added provider prefixesapps/ccusage/src/_glm-macro.ts- GLM prefetching logic (new file)apps/ccusage/src/_pricing-fetcher.ts- Updated to include GLM modelsTechnical Details
Closes #656
🤖 Generated with Claude Code
Summary by CodeRabbit