mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
docs(changelog): expand unreleased Codex usage fix notes to house style
This commit is contained in:
+12
-4
@@ -7,15 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **"Rebuild Codex Usage" Maintenance Action**: The usage dashboard's maintenance section gains a "Rebuild Codex Usage" button that backs up the database, wipes only `codex_session`-sourced detail rows, their `_codex_session` daily rollups, and the Codex sync cursors, then re-imports every rollout file from scratch with the corrected parser — the recovery path for databases already inflated by the fork double-count bug below, and the retry path for deferred fork files whose parent log has since been restored. The manual rebuild fails hard when the pre-rebuild backup cannot be written (unlike the automatic migration variant, which only warns, since blocking startup on an unwritable backup directory would leave the app unable to launch after upgrade), holds the session-sync lock across the whole backup → reset → reimport sequence so the 60-second background sync cannot interleave with the wipe, and always sends exactly one frontend refresh notification on completion — including when the reimport returns zero rows or fails after the reset — so the dashboard never keeps showing pre-reset numbers (`finish_codex_rebuild` in `commands/usage.rs`, pinned by two regression tests). Cursor deletion matches rollout paths purely by shape (`rollout-{uuid}` filename under a `sessions`/`archived_sessions` segment), so cursors recorded under an old `CODEX_HOME` are still cleaned. Localized in all four locales (zh/en/ja/zh-TW).
|
||||
- **Session Import Observability: Deferred Files and Suspected Duplicates**: Session sync results now report `filesScanned`, `deferredFiles` — fork rollouts whose parent log is missing or whose parent markers conflict, held back without writing a cursor so a later sync or manual rebuild retries them, instead of being imported on a guess — and `suspectedDuplicates`, backed by a post-insert probe that checks each imported row for a pre-existing same-fingerprint row (via the `idx_request_logs_dedup_lookup_expr` expression index) and logs a warning per hit, so any future regression of the double-count bug announces itself in the logs instead of silently inflating totals.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Codex Session Usage Rebuild and Fork Deduplication**: Codex fork/subagent rollouts now strip copied parent token history by matching explicit parent IDs against the parent rollout's pre-fork token signatures. Proxy usage logging also derives stable, provider-scoped response IDs and is idempotent at the final database write. Session importers are serialized and send one refresh notification per sync.
|
||||
- **Codex Fork/Sub-Agent Rollouts No Longer Import Replayed Parent History**: Fixes the v3.17.0 usage inflation where forking a Codex task or spawning a sub-agent in copy mode re-counted the parent conversation's token history as new usage — reports showed single days jumping by billions of tokens, duplicated parent/child rows that were byte-identical, and empty forks carrying usage they never consumed. Fork and sub-agent rollout files begin by replaying the parent thread's history, and the previous parser located the takeover boundary heuristically (first `thread_settings_applied` event, object-shaped `subagent` source markers): the boundary landed too early when the parent's own settings changes appeared in the replay, and was missed entirely for the current string-shaped source format, importing the whole replayed parent history. The parser now identifies a fork only by explicit parent identity — `forked_from_id` on the child's `session_meta` or `source.subagent.thread_spawn.parent_thread_id`, with a conflict between the two deferring the file — anchors each thread's identity to the rollout filename UUID, loads the parent rollout's own pre-fork token-count sequence, and strips the child's replayed prefix by aligning token signatures against it, so replayed events only restore the cumulative baseline and are never inserted as rows. Sub-agent logs that carry no replayed history are now counted as live usage, fixing the opposite-direction undercount where real sub-agent consumption was skipped as suspected replay. (#5335, #5433, #5381)
|
||||
- **Proxy Usage Logging Is Now Idempotent With Stable Response-Scoped Keys**: When a terminal usage event carried no message id — the norm for Codex `/responses` traffic through the local proxy — the dedup key fell back to a random UUID, so every retry or replay of the same upstream response minted a fresh key and `INSERT OR REPLACE` stacked a new row each time; one reporter's database held the same usage combination 2,078 times. The parser now derives the key from the response envelope itself — the Codex `response.completed` event's `response.id` (`response.created` ids are discarded), Chat Completions `chatcmpl` ids, and the Gemini `responseId` — scoped as `session:{app_type}:{provider_id}:{id}` so the same response replayed against a different provider during failover still bills once per provider without cross-provider collisions (Claude keeps the bare `session:{id}` shape so proxy rows continue to converge with session-log imports). When no envelope id exists at all, the fallback is a deterministic SHA-256 over the response's usage semantics rather than a random UUID — an identical replay must collide into the same key for dedup to work — and the final database write is a guarded insert-if-absent within the dedup window instead of an unconditional REPLACE. (#5496)
|
||||
- **Usage Page No Longer Freezes During Large Session Imports**: Opening the usage page while a big import ran could lock up the UI: every inserted row fired a refresh notification, each notification made the frontend re-run all ~10 usage queries, and those queries contended with the importer for the single database connection while it parsed rollout files tens of megabytes large line by line — on duplicate-inflated databases the row storm compounded all three. Session sync now notifies the frontend once per completed sync pass instead of once per row, all session importers are serialized behind a single-flight lock (a manual "sync now" queues behind the running pass instead of racing it), the blocking parse work runs on a dedicated blocking thread so it no longer starves the async runtime driving the UI's commands, and the 60-second background tick skips missed runs instead of bursting to catch up.
|
||||
|
||||
### Upgrade notes
|
||||
|
||||
- Schema v16 automatically rebuilds only `codex_session` usage. A pre-migration database backup is stored under `backups/`, but history whose source JSONL was already deleted cannot be reconstructed.
|
||||
- Fork files whose parent rollout is missing are deferred and reported instead of guessed; restoring the parent log and using “Rebuild Codex Usage” imports them later.
|
||||
- Existing historical proxy-source duplicate rows are not removed by this migration; the idempotent logger prevents future duplicates.
|
||||
- Schema v16 performs a one-time automatic rebuild of Codex session usage on first launch after upgrading: the database is backed up under `backups/`, `codex_session` data and cursors are reset, and the normal startup sync re-imports everything with the corrected parser. Expect seconds for typical data; the heaviest dataset measured (1,801 rollout files / 1.5 GB) took about 65 seconds. Later launches are incremental as before.
|
||||
- The rebuild recomputes usage from the rollout JSONL files, so history whose source log was already deleted cannot be reconstructed.
|
||||
- Fork files whose parent rollout is missing are deferred and reported instead of guessed; restoring the parent log and running “Rebuild Codex Usage” imports them later.
|
||||
- Historical proxy-source duplicate rows are permanently retained — the migration rebuilds only session-sourced data, and no cleanup pass for past proxy inflation exists; the idempotent logger prevents new duplicates from this point on.
|
||||
|
||||
## [3.17.0] - 2026-07-13
|
||||
|
||||
|
||||
Reference in New Issue
Block a user