perf(pricing): shrink embedded snapshots 58% and binary 2.9% - #1244
Conversation
Add a repo-local rust-binary-size skill for release-profile, dependency feature, native package size, and executable bloat work. The skill captures stable min-sized-rust guidance, keeps aggressive nightly and packer techniques opt-in, and links back to the upstream reference so future agents can inspect the source material when size work recurs. Register the skill in AGENTS.md so agents discover it before changing Rust size-sensitive code or packaging.
Regenerate the committed models.dev pricing snapshot as a flat map keyed by runtime model id instead of preserving upstream provider nesting. The runtime loader now accepts both the live provider-tree shape from models.dev and the flat embedded shape, so network fallback compatibility is unchanged while the checked-in snapshot shrinks from 97,159 bytes to 36,871 bytes. The release binary rebuilt successfully after the change at 2,845,920 bytes. Pricing tests cover the flat embedded shape and the existing offline fallback behaviour.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | d4311b9 | Commit Preview URL Branch Preview URL |
Jun 10 2026, 04:25 PM |
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a rust-binary-size skill doc and registers it; changes models.dev generation to a flat embedded map, compacts LiteLLM entries in the build, extends Rust pricing parsers for compact and flattened/provider-wrapped shapes with tests, adds a macOS staging rewrite, and makes performance-run installation tolerant of timeouts. ChangesRust binary size skill documentation
Models.dev pricing format migration
Native packaging
PR comment script
Performance comparison runner
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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.
✅ No new issues found.
Reviewed changes — flattens the embedded models.dev pricing snapshot to shrink the release binary and adds a repo-local rust-binary-size skill.
- Add
rust-binary-sizeskill — stable binary-size guidance from min-sized-rust with investigation steps, safe/risky change categories, and validation commands. - Register skill in
AGENTS.md— addsrust-binary-sizeto the skill routing list. - Flatten
models-dev-pricing.json— regenerates the snapshot as a flat map keyed by runtime model id, shrinking from ~97KB to ~37KB. - Make loader format-agnostic —
ModelsDevJsonuntagged enum accepts both provider-tree (live models.dev) and flat (embedded) formats;load_models_dev_modelsis extracted for reuse. - Update generator —
nix/models-dev-gen.tsoutputs flat entries withmodel.id ?? modelIdas the key and first-wins dedup.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
rust/crates/ccusage/src/pricing.rs (1)
1486-1514: ⚡ Quick winPrefer a fixture-backed parser case for the flat snapshot.
This inline JSON is already large, and the flat-vs-provider compatibility matrix will likely grow. Moving this case into a fixture will keep the test readable and make future parser regressions easier to extend.
As per coding guidelines, "For Rust code, keep modules small, keep
pub(crate)surfaces narrow, prefer fixture-backed parser/loader tests, and run cargo checks through thejustrecipes when possible."🤖 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 `@rust/crates/ccusage/src/pricing.rs` around lines 1486 - 1514, The test loads_flat_models_dev_pricing_snapshot embeds a large inline JSON; move this into a fixture file and update the test to read and pass that fixture to PricingMap::load_models_dev_json_missing to keep the test small and maintainable. Create a fixture (e.g., tests/fixtures/claude_flat_snapshot.json) containing the JSON, update the test in loads_flat_models_dev_pricing_snapshot to read the fixture (using std::fs::read_to_string or the test helper used elsewhere), and keep assertions that call PricingMap::default(), pricing.load_models_dev_json_missing(...), pricing.find("claude-fallback"), and pricing.context_limit("claude-fallback") unchanged. Ensure the test still asserts Some(1) from load_models_dev_json_missing and the same numeric checks for fallback.input, fallback.output, fallback.cache_create, and fallback.cache_read.Source: Coding guidelines
🤖 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 `@rust/crates/ccusage/src/pricing.rs`:
- Around line 90-95: The untagged ModelsDevJson enum allows provider objects to
be mis-parsed as flat model entries, so replace the #[serde(untagged)] approach
with explicit shape validation: implement a custom Deserialize (or parse
serde_json::Value) for ModelsDevJson that inspects each top-level entry and
requires a "models" field for provider entries (mapping to ModelsDevProvider)
and requires "cost"/"input"/"output" fields for flat ModelsDevModel entries,
returning a clear error if a provider entry is missing "models"; update
load_models_dev_models to use the new validated ModelsDevJson and ensure
ModelsDevPricingCache::get_or_try_load still only caches successful,
non-malformed results (i.e., parsing must error instead of returning an empty
map), and add a fixture-backed regression test that loads a mixed/malformed
providers file (one provider missing "models") asserting parsing fails and no
empty PricingMap is cached.
---
Nitpick comments:
In `@rust/crates/ccusage/src/pricing.rs`:
- Around line 1486-1514: The test loads_flat_models_dev_pricing_snapshot embeds
a large inline JSON; move this into a fixture file and update the test to read
and pass that fixture to PricingMap::load_models_dev_json_missing to keep the
test small and maintainable. Create a fixture (e.g.,
tests/fixtures/claude_flat_snapshot.json) containing the JSON, update the test
in loads_flat_models_dev_pricing_snapshot to read the fixture (using
std::fs::read_to_string or the test helper used elsewhere), and keep assertions
that call PricingMap::default(), pricing.load_models_dev_json_missing(...),
pricing.find("claude-fallback"), and pricing.context_limit("claude-fallback")
unchanged. Ensure the test still asserts Some(1) from
load_models_dev_json_missing and the same numeric checks for fallback.input,
fallback.output, fallback.cache_create, and fallback.cache_read.
🪄 Autofix (Beta)
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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 37d352af-ba08-4f3c-95dd-6071e00b9885
📒 Files selected for processing (5)
.agents/skills/rust-binary-size/SKILL.mdAGENTS.mdnix/models-dev-gen.tsrust/crates/ccusage/src/models-dev-pricing.jsonrust/crates/ccusage/src/pricing.rs
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-darwin-x64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-arm64
@ccusage/ccusage-win32-x64
commit: |
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="rust/crates/ccusage/src/pricing.rs">
<violation number="1" location="rust/crates/ccusage/src/pricing.rs:294">
P1: load_models_dev_json_missing returns Some(0) on zero models loaded, which the caller treats as success and caches permanently in OnceLock — silently disabling the entire models.dev fallback for the process lifetime.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| Some(match raw { | ||
| ModelsDevJson::Providers(providers) => providers | ||
| .into_values() | ||
| .map(|provider| self.load_models_dev_models(provider.models)) | ||
| .sum(), | ||
| ModelsDevJson::Models(models) => self.load_models_dev_models(models), | ||
| }) |
There was a problem hiding this comment.
P1: load_models_dev_json_missing returns Some(0) on zero models loaded, which the caller treats as success and caches permanently in OnceLock — silently disabling the entire models.dev fallback for the process lifetime.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At rust/crates/ccusage/src/pricing.rs, line 294:
<comment>load_models_dev_json_missing returns Some(0) on zero models loaded, which the caller treats as success and caches permanently in OnceLock — silently disabling the entire models.dev fallback for the process lifetime.</comment>
<file context>
@@ -281,56 +288,64 @@ impl PricingMap {
+ let Ok(raw) = serde_json::from_str::<ModelsDevJson>(json) else {
return None;
};
+ Some(match raw {
+ ModelsDevJson::Providers(providers) => providers
+ .into_values()
</file context>
| Some(match raw { | |
| ModelsDevJson::Providers(providers) => providers | |
| .into_values() | |
| .map(|provider| self.load_models_dev_models(provider.models)) | |
| .sum(), | |
| ModelsDevJson::Models(models) => self.load_models_dev_models(models), | |
| }) | |
| let count = match raw { | |
| ModelsDevJson::Providers(providers) => providers | |
| .into_values() | |
| .map(|provider| self.load_models_dev_models(provider.models)) | |
| .sum(), | |
| ModelsDevJson::Models(models) => self.load_models_dev_models(models), | |
| }; | |
| if count == 0 { | |
| None | |
| } else { | |
| Some(count) | |
| } |
Replace the untagged models.dev snapshot parser with explicit top-level shape validation so malformed provider payloads cannot be accepted as an empty flat model map. The regression test uses a fixture-backed malformed provider payload and confirms parsing fails without loading entries. This addresses CodeRabbit feedback on PR #1244. Validation: direnv exec . cargo test --manifest-path rust/Cargo.toml -p ccusage pricing::tests:: -- --nocapture; direnv exec . just fmt
Emit the build-time LiteLLM snapshot with short field keys and teach the runtime loader to read both the compact embedded shape and the normal LiteLLM response shape. The generated LiteLLM snapshot shrinks from 66,046 bytes to 31,949 bytes while keeping 401 model keys. Runtime-relevant fields compared equal after expanding the compact keys. Together with the models.dev flattening, the local release binary is now 2,812,864 bytes versus 2,895,424 bytes on the base commit. Validation: direnv exec . cargo test --manifest-path rust/Cargo.toml -p ccusage pricing::tests:: -- --nocapture; direnv exec . cargo build --manifest-path rust/Cargo.toml --release --bin ccusage; direnv exec . just fmt
|
@coderabbitai review\n\nPushed follow-up commits through 015de4c. Addressed your models.dev parser feedback by replacing untagged deserialization with explicit shape validation and a fixture-backed malformed-provider regression test. Also compacted the embedded LiteLLM snapshot after validating key/value parity for runtime-relevant fields. Validation: direnv exec . just fmt, direnv exec . just test, pricing::tests::, release build. |
|
✅ Action performedReview finished.
|
|
@cubic-dev-ai review it |
@ryoppippi I have started the AI code review. It will take a few minutes to complete. |
|
Run failed. View the logs →
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — compacts the embedded LiteLLM snapshot with short key names and replaces #[serde(untagged)] deserialization with explicit shape validation for models.dev payloads, addressing the prior CodeRabbit concern about silent mis-parsing.
- Compact LiteLLM embedded snapshot —
build.rsmaps long field names to short keys (i,o,cc,cr,ia,oa,cca,cra,ctx,fast).parse_litellm_pricingdetects compact format by the"i"key and falls back to fullLiteLlmPricingdeserialization for live upstream responses. - Explicit models.dev shape validation —
parse_models_dev_jsoninspects top-level entries to distinguish provider-tree payloads (all entries have"models"object) from flat payloads (all entries havecost.input/cost.outputnumbers), rejecting mixed or malformed inputs. Replaces the prior#[serde(untagged)]approach. - Extract
load_models_dev_models— inline model-loading loop moved into its own method, called from both provider and flat branches ofload_models_dev_json_missing.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
🧹 Nitpick comments (1)
rust/crates/ccusage/src/pricing.rs (1)
987-1013: ⚡ Quick winAlign compact-shape detection with the emitter contract (
i+o).Line 990 checks only
"i"to enter compact parsing, but the emitter only produces compact entries when both"i"and"o"are present (build.rs Line 134). Matching that condition (and falling back to full-shape parse if compact decode fails) avoids false positives and accidental drops.♻️ Suggested patch
fn parse_litellm_pricing(value: Value) -> Option<LiteLlmPricing> { - if value - .as_object() - .is_some_and(|entry| entry.contains_key("i")) - { - let compact = serde_json::from_value::<CompactLiteLlmPricing>(value).ok()?; - return Some(LiteLlmPricing { - input_cost_per_token: Some(compact.i), - output_cost_per_token: Some(compact.o), - cache_creation_input_token_cost: compact.cc, - cache_read_input_token_cost: compact.cr, - input_cost_per_token_above_200k_tokens: compact.ia, - output_cost_per_token_above_200k_tokens: compact.oa, - cache_creation_input_token_cost_above_200k_tokens: compact.cca, - cache_read_input_token_cost_above_200k_tokens: compact.cra, - max_input_tokens: compact.ctx, - provider_specific_entry: compact - .fast - .map(|fast| ProviderSpecificEntry { fast: Some(fast) }), - }); + if value.as_object().is_some_and(|entry| { + entry.contains_key("i") && entry.contains_key("o") + }) { + if let Ok(compact) = serde_json::from_value::<CompactLiteLlmPricing>(value.clone()) { + return Some(LiteLlmPricing { + input_cost_per_token: Some(compact.i), + output_cost_per_token: Some(compact.o), + cache_creation_input_token_cost: compact.cc, + cache_read_input_token_cost: compact.cr, + input_cost_per_token_above_200k_tokens: compact.ia, + output_cost_per_token_above_200k_tokens: compact.oa, + cache_creation_input_token_cost_above_200k_tokens: compact.cca, + cache_read_input_token_cost_above_200k_tokens: compact.cra, + max_input_tokens: compact.ctx, + provider_specific_entry: compact + .fast + .map(|fast| ProviderSpecificEntry { fast: Some(fast) }), + }); + } } let pricing = serde_json::from_value::<LiteLlmPricing>(value).ok()?; pricing🤖 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 `@rust/crates/ccusage/src/pricing.rs` around lines 987 - 1013, In parse_litellm_pricing: the compact-shape detection should require both "i" and "o" (not just "i") and must not abort if compact deserialization fails; change the condition that checks the Value object to require entry.contains_key("i") && entry.contains_key("o"), and when attempting serde_json::from_value::<CompactLiteLlmPricing>(value) handle failure by falling through to the normal serde_json::from_value::<LiteLlmPricing>(value) path instead of using the ? to return early; keep the existing mapping that converts CompactLiteLlmPricing into LiteLlmPricing (using CompactLiteLlmPricing, LiteLlmPricing, and ProviderSpecificEntry identifiers).
🤖 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.
Nitpick comments:
In `@rust/crates/ccusage/src/pricing.rs`:
- Around line 987-1013: In parse_litellm_pricing: the compact-shape detection
should require both "i" and "o" (not just "i") and must not abort if compact
deserialization fails; change the condition that checks the Value object to
require entry.contains_key("i") && entry.contains_key("o"), and when attempting
serde_json::from_value::<CompactLiteLlmPricing>(value) handle failure by falling
through to the normal serde_json::from_value::<LiteLlmPricing>(value) path
instead of using the ? to return early; keep the existing mapping that converts
CompactLiteLlmPricing into LiteLlmPricing (using CompactLiteLlmPricing,
LiteLlmPricing, and ProviderSpecificEntry identifiers).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e6a28294-2356-4e8d-91b1-b9a4f3b3e52e
📒 Files selected for processing (2)
rust/crates/ccusage/build.rsrust/crates/ccusage/src/pricing.rs
There was a problem hiding this comment.
1 issue found across 6 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="rust/crates/ccusage/src/pricing.rs">
<violation number="1" location="rust/crates/ccusage/src/pricing.rs:294">
P1: load_models_dev_json_missing returns Some(0) on zero models loaded, which the caller treats as success and caches permanently in OnceLock — silently disabling the entire models.dev fallback for the process lifetime.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
The Failure: Why it's unrelated: This PR only touches pricing JSON snapshot compaction ( No changes are needed for this PR. Task list (4/4 completed)
|
Align the LiteLLM compact-shape detector with the build-time emitter by requiring both short price keys before compact decoding. If compact decoding fails, the parser now falls back to the full LiteLLM shape so unrelated metadata keys do not drop otherwise valid pricing rows. Also make the models.dev snapshot generator ignore empty catalog ids and fall back to the source model key. This prevents a malformed empty id from becoming the embedded pricing key while keeping the committed snapshot format unchanged.
The macOS native package was copying a Nix-built binary that still referenced libiconv inside /nix/store. That works inside a Nix closure but fails when the binary is installed from the npm preview package on a clean GitHub macOS runner. Patch the staged Darwin binary with install_name_tool so the package uses /usr/lib/libiconv.2.dylib at runtime. This keeps the Nix build unchanged while making the published native package runnable outside Nix.
|
@coderabbitai review Pushed follow-up commits through 465d2bc. Addressed the latest CodeRabbit LiteLLM parser feedback in 3684c80 by requiring both compact emitter keys (i + o), falling back to full LiteLLM parsing if compact decode does not apply, and adding a regression test for a full-shape entry with an extra i key. Also addressed cubic finding in 3684c80 by falling back to the source model key when the models.dev catalog id is empty, with a Vitest case included. Fixed the failing macOS preview package E2E in 465d2bc by rewriting the staged Darwin binary Nix-store libiconv install name to /usr/lib/libiconv.2.dylib. Verified locally with otool after staging. Validation:
|
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — hardens compact LiteLLM pricing parsing to require both "i" and "o" with fall-through on parse failure, rewrites Nix-built Darwin libiconv install names for macOS compatibility, refactors the models.dev generator key selection into a testable module, and wires the new Vitest nix project.
- Harden compact LiteLLM parsing —
parse_litellm_pricingnow requires both"i"and"o"keys and falls through to full-shape deserialization when compact deserialization fails (e.g."i"as a string in upstream responses), matching thebuild.rsemitter contract. Added a dedicated regression test for the fall-through path. - Fix Darwin packaging —
stage-native-package.mjsnow callsinstall_name_toolto rewrite Nix-storelibiconv.2.dylibpaths to/usr/lib/libiconv.2.dylibon macOS. - Extract
selectModelsDevPricingKey— moved key-selection logic from the inline generator intonix/models-dev-compact.tswith a Vitest test. Empty-string catalog IDs now fall back to the model ID. - Wire
nixVitest project —vitest.config.tsnow discovers tests undernix/**/*.test.ts.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
1 issue found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="rust/crates/ccusage/src/pricing.rs">
<violation number="1" location="rust/crates/ccusage/src/pricing.rs:294">
P1: load_models_dev_json_missing returns Some(0) on zero models loaded, which the caller treats as success and caches permanently in OnceLock — silently disabling the entire models.dev fallback for the process lifetime.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
No new issues. The two changes since the last pullfrog review are test-coverage additions only — new Task list (5/5 completed)
|
|
✅ Action performedReview finished.
|
@ryoppippi I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
1 issue found across 10 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="nix/models-dev-gen.ts">
<violation number="1" location="nix/models-dev-gen.ts:50">
P3: Duplicate pricing keys are silently dropped with `continue`. If two providers map to the same key with different pricing, the first wins silently. Consider emitting a warning when a duplicate is skipped so pricing drift is visible during future snapshot regenerations.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Perf comment jobs use pkg.pr.new URLs for both the base and PR package. The base URL can be unavailable for a commit that was never published by the preview package workflow, which previously made the script wait for the full job timeout and fail before writing a comment. Make package installation return undefined when the URL is not ready, emit a commit-specific skipped performance comment when no base-dir fallback exists, and lower the workflow wait to five minutes so the job has time to finish cleanly.
The compact models.dev generator keeps the first entry for a pricing key, but duplicate provider aliases were previously skipped without any signal. Cubic identified that this could hide future pricing drift when regenerating the snapshot. Emit a warning before skipping a duplicate pricing key and cover the warning text with a focused Vitest case so future duplicate handling remains visible.
|
@coderabbitai review Pushed follow-up commits
Validated locally with |
@ryoppippi I have started the AI code review. It will take a few minutes to complete. |
|
Action performedReview triggered.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — three follow-up commits that harden the perf commentary CI job, add a duplicate-key warning during models.dev snapshot generation, and improve test coverage.
- Reduce perf-comment timeout to 5 minutes — CI jobs now wait only 5 minutes for
pkg.pr.newURLs instead of 30, matching theinstallPackageUrlcontract change below. - Gracefully skip when base package URL is unavailable —
installPackageUrlreturnsundefinedinstead of throwing; the main command handler renders a skip comment and exits cleanly when a base package is needed but can't be installed and no--base-diris provided. - Log duplicate models.dev pricing key warnings —
models-dev-gen.tsnow callsconsole.warnvia the extractedformatDuplicateModelsDevPricingKeyWarninghelper when two source models map to the same flat key, addressing the Cubic duplicate-key concern. - Fill
selectModelsDevPricingKeytest matrix — added tests forundefinedand non-empty catalog IDs alongside the existing empty-string case, plus a formatting test for the warning helper. - Make LiteLLM fall-through test more precise — the
"gpt-full-with-extra-i"fixture now includes"o": "provider metadata"so the test correctly verifies the compact parser falls through on non-numeric"i"/"o"fields rather than on a missing"o"key.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
ccusage performance comparisonPR SHA: Performance comparison skipped. Base package URL was not ready before 300.000s. Fixture performance comparison requires a base package when --base-dir is not provided. Base package: |
ccusage performance comparisonPR SHA: Performance comparison skipped. Base package URL was not ready before 300.000s. Fixture performance comparison requires a base package when --base-dir is not provided. Base package: |
ccusage performance comparisonPR SHA: Performance comparison skipped. Base package URL was not ready before 300.000s. Fixture performance comparison requires a base package when --base-dir is not provided. Base package: |
CI failure analysisFailed job: Error: Verdict: NOT introduced by this PR. The failure is a GitHub API authentication flake unrelated to the PR's changes:
The other CI jobs (lint-check, test, build-native-packages) passed. No code fix is needed for this PR.
|
The rust perf comment job can produce a skipped benchmark summary when the base pkg.pr.new package is unavailable, but creating the new PR comment failed with a 401 from the workflow token. That made the job fail even though the benchmark script completed and wrote the job summary. Treat 401 the same as the existing 403 no-comment-permission path, keep other GitHub failures fatal, and add a small in-source Vitest project for this script so the auth classification is covered.
|
@coderabbitai review Pushed follow-up commit This fixes the remaining Validated locally with |
@ryoppippi I have started the AI code review. It will take a few minutes to complete. |
|
Action performedReview triggered.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — hardens the PR comment script against unauthenticated writes (401) and wraps it in testable shape.
- Tolerate 401 comment-write failures —
isCommentWriteAuthFailurenow checks 401 alongside 403 so read-only tokens don't crash the script. - Extract
main()and parameterize helpers —createCommentandtryCreateCommentacceptrepository/prNumber/bodyas parameters instead of closing over top-level variables. - Add inline Vitest tests — three tests cover the
isCommentWriteAuthFailuretype guard for 401, 403, and 500. - Wire
github-scriptsVitest project —ci.yamlruns the inline tests under a dedicated project withincludeSource.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Reviewed changes — shrinks embedded pricing snapshots 58%, adds a Rust binary-size skill, hardens CI performance-comparison resilience against unavailable artifacts, and fixes macOS packaging libiconv linkage.
- Add
rust-binary-sizeskill — repo-local guidance for release profiles, dependency features, and binary bloat investigation based on min-sized-rust. - Compact embedded pricing snapshots — short field names in
build.rsreduce JSON payload from 163 KB to 69 KB, with compatibleCompactLiteLlmPricingparsing inpricing.rs. - Flatten models.dev embedding —
models-dev-gen.tsoutputs a flat map keyed by runtime model id instead of a provider-nested object;pricing.rsaccepts both the new flat shape and the legacy provider shape. - Skip unavailable base packages gracefully —
compare-pr-performance.tsreturns a commit-specific skip comment instead of throwing when the base package URL isn't ready before the timeout. - Try harder on comment write auth failures —
upsert-pr-comment.tstreats 401 like the existing 403 no-comment-permission path; adds in-source tests via thegithub-scriptsvitest workspace. - Rewrite Nix libiconv on macOS —
stage-native-package.mjsreplaces the Nix storelibiconv.2.dylibwith/usr/lib/libiconv.2.dylibviainstall_name_tool. - Reduce CI perf timeout —
--package-runner-timeout-msdrops from 30 min to 5 min in both codex and rust perf jobs. - Expand vitest workspace — adds
nixandgithub-scriptstest projects so compact-pricing helpers and upsert script tests participate in CI.
✅ No new issues found.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
1 issue found across 13 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/ccusage/scripts/stage-native-package.mjs">
<violation number="1" location="apps/ccusage/scripts/stage-native-package.mjs:33">
P1: install_name_tool invalidates the Mach-O code signature; re-sign with `codesign --force --sign -` afterward or the distributed macOS binary may fail to launch on Apple Silicon due to signature enforcement.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| for (const line of linkedLibraries.split('\n')) { | ||
| const library = line.trim().split(/\s+/)[0]; | ||
| if (/^\/nix\/store\/[^/]+-libiconv-[^/]+\/lib\/libiconv\.2\.dylib$/.test(library)) { | ||
| execFileSync('install_name_tool', [ |
There was a problem hiding this comment.
P1: install_name_tool invalidates the Mach-O code signature; re-sign with codesign --force --sign - afterward or the distributed macOS binary may fail to launch on Apple Silicon due to signature enforcement.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/ccusage/scripts/stage-native-package.mjs, line 33:
<comment>install_name_tool invalidates the Mach-O code signature; re-sign with `codesign --force --sign -` afterward or the distributed macOS binary may fail to launch on Apple Silicon due to signature enforcement.</comment>
<file context>
@@ -24,6 +25,21 @@ function readOption(name, fallback) {
+ for (const line of linkedLibraries.split('\n')) {
+ const library = line.trim().split(/\s+/)[0];
+ if (/^\/nix\/store\/[^/]+-libiconv-[^/]+\/lib\/libiconv\.2\.dylib$/.test(library)) {
+ execFileSync('install_name_tool', [
+ '-change',
+ library,
</file context>
* fix(pricing): copy models-dev-compact.ts into the Bun build sandbox The models.dev pricing generator was split in #1244 so that nix/models-dev-gen.ts imports its sibling ./models-dev-compact.ts. The Nix derivation only copied gen.ts into the writable workspace, so Bun could not resolve the new import inside the sandbox: error: Cannot find module './models-dev-compact.ts' from '/build/work/gen.ts' This broke the scheduled "update pricing" workflow on the update-models-dev-pricing job and every manual gen-models-dev-pricing run. Copy models-dev-compact.ts alongside gen.ts under the same relative name the import expects. Verified locally: the regenerated snapshot is byte-identical to the committed rust/crates/ccusage/src/models-dev-pricing.json. * fix(ci): force-push the pricing automation branches without a lease The "Create pull request" steps pushed with --force-with-lease, but the job checks out main at fetch-depth 1 and never fetches the bot branch. Without a remote-tracking ref, git refuses the lease: ! [rejected] automation/litellm-pricing -> automation/litellm-pricing (stale info) error: failed to push some refs These branches are written only by this workflow, so a plain --force is safe and is the standard pattern for a bot-owned automation branch.

Adds a repo-local Rust binary-size skill based on min-sized-rust and registers it in AGENTS.md.
Applies that guidance by compacting embedded pricing snapshots so the release binary ships less unused JSON structure while keeping runtime parsing compatible with live upstream response shapes.
Impact:
Data integrity:
Testing:
Summary by CodeRabbit
Documentation
Improvements
Bug Fixes
CI / Tooling