Skip to content

feat(zcode): add Z.ai usage adapter - #1

Merged
axisrow merged 6 commits into
mainfrom
ao/ccusage-2/zcode
Aug 12, 2026
Merged

axisrow merged 6 commits into
mainfrom
ao/ccusage-2/zcode

Conversation

@axisrow

@axisrow axisrow commented Aug 11, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add the read-only SQLite-backed ccusage zcode adapter for ZCode (Z.ai)
  • count only completed model-usage rows; normalize cache-inclusive input tokens and calculate GLM-5.2 costs from embedded pricing
  • include ZCode in unified reports, CLI/config schema, snapshots, and user documentation
  • apply zcode.defaults and zcode.commands.<report> configuration blocks
  • retain arbitrary custom-provider models when their pricing is unavailable: auto and calculate report zero cost and a missing-pricing warning; display reports zero cost

Validation

  • cargo fmt --check
  • cargo clippy --workspace --all-targets
  • RUST_TEST_THREADS=4 cargo test -p ccusage — 307 passed, 1 local-data smoke test ignored
  • RUST_TEST_THREADS=4 cargo test --workspace — 377 passed, 1 local-data smoke test ignored (before the final config-only regression test)
  • JSON schema and CLI-help snapshots updated

The branch was rebuilt from current origin/main and contains only the ZCode adapter, integration, test/snapshot, pricing, configuration, and documentation changes. Nix-specific just checks remain for CI because the local Nix dev shell is unavailable.

@axisrow

axisrow commented Aug 11, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai @cubic-dev-ai Please review the new ZCode adapter, especially SQLite token normalization, cost-mode semantics, and unified aggregation wiring.

@axisrow axisrow left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Reviewed the ZCode (Z.ai) adapter PR (head be01497).

Summary: New read-only SQLite-backed adapter under rust/crates/ccusage/src/adapter/zcode/, wired into the unified all report, CLI parser/commands, config schema, JSON schema, docs, and pricing table (embedded GLM-5.2 fallback pricing). Well-covered with fixture-backed tests (path discovery, parser normalization, loader completed/non-completed filtering, report aggregation snapshot) plus a skipped local-data smoke test.

Findings (non-blocking, informational):

  • parser.rs: read_model_usage_row deliberately ignores mu.reasoning_tokens (selected in the SQL query but never read at index 6) because ZCode already folds reasoning tokens into output_tokens. This is documented in adapter/zcode/README.md ("ZCode already includes reasoning_tokens in its output-token accounting"), so it reads as an intentional, well-explained design decision rather than dead code - just flagging it since an unused SELECT column is easy to mistake for an oversight on a future pass.
  • pricing.rs: GLM-5.2 pricing (input 1.4e-6 / output 4.4e-6 / cache 0.26e-6) is hardcoded as a built-in fallback rather than sourced from LiteLLM/models.dev, consistent with how ZCode reports no native USD cost. Worth keeping an eye on for staleness if Z.ai changes pricing, but matches the pattern used elsewhere in this file for similar offline fallbacks.
  • report.rs: summarize_entries/rows_key implement a Weekly branch that the CLI parser never exposes for zcode (agent_report_supported only allows daily/monthly/session, matching STANDARD_AGENT_REPORTS). Harmless (mirrors the shared match pattern from other standard adapters like goose), just unreachable from the CLI today.

No correctness bugs, missing error handling, or security issues found. Token normalization (input_tokens - cache_read - cache_creation) is documented and covered by a dedicated regression test/snapshot. Documentation (README, docs guide, VitePress nav, getting-started env var tables) is updated consistently for the new adapter. Config/JSON schema additions and CLI snapshots look complete and consistent with sibling adapters.

Approving - ready to merge as-is.

pub(super) timestamp: TimestampMs,
pub(super) directory: Option<String>,
pub(super) usage: TokenUsageRaw,
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

SQL selects mu.reasoning_tokens (index 6) but read_model_usage_row never reads it - confirmed intentional per adapter README (ZCode already includes reasoning tokens in output_tokens), just flagging since it reads like an unused column at a glance.

..glm_base
},
);
let glm_5_2 = Pricing {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

GLM-5.2 pricing is hardcoded here as an offline fallback rather than sourced from LiteLLM/models.dev - reasonable given ZCode reports no native cost, but will need manual updates if Z.ai changes pricing.

@axisrow

axisrow commented Aug 12, 2026

Copy link
Copy Markdown
Owner Author

🔍 Local review (cycle-review, round 4298e3fa-daae-4bc1-aa72-c4a09d96c5b0)

Reviewed locally via the built-in /review plus the Codex companion (background, parallel). No GitHub bots pinged.

Verdict Reviewer Finding Location
SKIP codex ZCode auto-mode token pricing mirrors the same recorded-cost fallback used by every other adapter and is already disclosed in the adapter README and docs guide rust/crates/ccusage/src/adapter/zcode/parser.rs:100-111
FIX codex The zcode agent name is missing from config.rs is_agent_command, so a zcode.defaults or zcode.commands.daily block in ccusage.json is silently never applied to CLI runs rust/crates/ccusage/src/config.rs:234-253
HALLUCINATION claude The new AgentLoadSpec index used for zcode in the unified loader array is unique; no other spec collides with it rust/crates/ccusage/src/adapter/all/loader.rs
SKIP claude The zero-usage row filter in the SQLite reader intentionally and correctly drops genuinely empty rows before aggregation rust/crates/ccusage/src/adapter/zcode/parser.rs:33-42
SKIP claude Returning an error when HOME is unset and ZCODE_HOME is not set matches the existing goose adapter pattern, not a regression introduced by this PR rust/crates/ccusage/src/adapter/zcode/paths.rs:16-20
SKIP claude Stopping the per-file scan on a SQLite read error while keeping already-collected rows is a reasonable partial-read fallback, consistent with the rest of the loader rust/crates/ccusage/src/adapter/zcode/loader.rs:66-84

Totals: 1 FIX (not yet applied — see note), 4 SKIP, 1 HALLUCINATION.

Note on the FIX item: this review session is scoped as a read-only reviewer (its file-edit tooling is disabled by design) and cannot apply, commit, or push the fix. Recommended change: add "zcode" to is_agent_command in rust/crates/ccusage/src/config.rs (alongside the other agent names), plus a regression test exercising detect_config_command/apply_config_to_shared for a zcode config block — mirroring the existing coverage for goose/openclaw. This should be applied in a follow-up commit from a session with write access before merge.

@axisrow
axisrow force-pushed the ao/ccusage-2/zcode branch from 327f28d to d2af646 Compare August 12, 2026 14:57
@axisrow
axisrow merged commit d8c966a into main Aug 12, 2026
15 checks passed
@axisrow
axisrow deleted the ao/ccusage-2/zcode branch August 12, 2026 17:48
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.

1 participant