codex-usage-tracking 0.4.1__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/.codex-plugin/plugin.json +1 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/CHANGELOG.md +9 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/PKG-INFO +29 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/README.md +28 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/cli-reference.md +2 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/dashboard-guide.md +9 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/development.md +10 -9
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/one-dot-oh-readiness.md +11 -9
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/pyproject.toml +2 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/scripts/check_release.py +101 -17
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/scripts/smoke_installed_package.py +12 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/skills/codex-usage-tracker/scripts/run_mcp.py +2 -2
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/__init__.py +1 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/cli.py +15 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/costing.py +14 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/dashboard.py +16 -2
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/i18n.py +182 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/dashboard/dashboard.css +20 -4
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/dashboard/dashboard.js +617 -303
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/dashboard_template.html +146 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/ar.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/de.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/en.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/es.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/fr.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/it.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/ja.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/ko.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/pt.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/ru.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/vi.json +438 -0
- codex_usage_tracking-0.5.0/src/codex_usage_tracker/plugin_data/dashboard/locales/zh-Hans.json +438 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/recommendations.py +11 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/server.py +9 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/PKG-INFO +29 -1
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/SOURCES.txt +14 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_cli_release.py +79 -2
- codex_usage_tracking-0.5.0/tests/test_i18n.py +402 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_pricing.py +45 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_recommendations.py +9 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_store_dashboard_mcp.py +52 -25
- codex_usage_tracking-0.4.1/src/codex_usage_tracker/plugin_data/dashboard/dashboard_template.html +0 -141
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/.mcp.json +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/AGENTS.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/CONTRIBUTING.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/LICENSE +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/MANIFEST.in +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/SECURITY.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/assets/icon.svg +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/architecture.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/dashboard-calls-preview.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/dashboard-calls.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/dashboard-details.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/dashboard-insights.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/dashboard-threads.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/plugin-prompts.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/plugin-thread-leaderboard.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/ux/call-detail-panel.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/ux/insight-overview.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/assets/ux/thread-investigation.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/cli-json-schemas.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/install.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/mcp.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/pricing-and-credits.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/privacy.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/docs/ui-ux-improvement-plan.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/scripts/benchmark_synthetic_history.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/scripts/install_local_plugin.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/setup.cfg +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/skills/codex-usage-api/SKILL.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/skills/codex-usage-tracker/SKILL.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/__main__.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/allowance.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/api_payloads.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/context.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/diagnostics.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/formatting.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/json_contracts.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/mcp_server.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/models.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/parser.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/paths.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/__init__.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/assets/icon.svg +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/dashboard/dashboard_data.js +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/dashboard/dashboard_format.js +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/dashboard/dashboard_state.js +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/docs/assets/dashboard-calls.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/docs/assets/dashboard-details.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/docs/assets/dashboard-insights.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/docs/assets/dashboard-threads.png +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/docs/dashboard-guide.html +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/skills/codex-usage-api/SKILL.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_data/skills/codex-usage-tracker/SKILL.md +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/plugin_installer.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/pricing.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/pricing_config.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/pricing_estimates.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/pricing_openai.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/projects.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/redaction.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/reports.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/schema.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/store.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/support.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/threads.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/dependency_links.txt +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/entry_points.txt +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/requires.txt +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracking.egg-info/top_level.txt +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_allowance.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_cli_lifecycle.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_dashboard_state.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_json_contracts.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_mcp_launcher.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_parser.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_plugin_installer.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_privacy.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_projects.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_schema.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_store_migrations.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_support.py +0 -0
- {codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/tests/test_threads.py +0 -0
|
@@ -2,9 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.5.0 - 2026-06-10
|
|
6
|
+
|
|
7
|
+
- Add the dashboard localization foundation, including starter locale catalogs, language metadata, local browser language selection, `--lang`, and `CODEX_USAGE_TRACKER_LANG`.
|
|
8
|
+
- Add Vietnamese dashboard localization and focused validation coverage for translated dashboard labels.
|
|
9
|
+
- Keep the README landing page focused on dashboard screenshots and companion usage workflows before detailed localization guidance.
|
|
10
|
+
- Stabilize the CI synthetic benchmark smoke so coverage instrumentation does not create false release failures.
|
|
11
|
+
- Pin the marketplace MCP runtime launcher to the exact `codex-usage-tracking==0.5.0` package.
|
|
12
|
+
|
|
5
13
|
## 0.4.1 - 2026-06-09
|
|
6
14
|
|
|
7
15
|
- Harden the production PyPI workflow so manual publishing must run from `main` or a tag ref before artifacts are downloaded and uploaded.
|
|
16
|
+
- Skip TestPyPI/PyPI uploads when the exact distribution version already exists on the target index, allowing a GitHub Release to be reconciled after a workflow-dispatch publish.
|
|
8
17
|
- Strengthen `scripts/check_release.py` so it validates the publish-ref preflight inside both the TestPyPI and PyPI jobs.
|
|
9
18
|
- Check off completed 1.0 readiness items with evidence for migration coverage, localhost dashboard smoke testing, and the protected GitHub `pypi` environment.
|
|
10
19
|
- Pin the marketplace MCP runtime launcher to the exact `codex-usage-tracking==0.4.1` package.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-usage-tracking
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Unofficial local Codex plugin and dashboard for investigating aggregate token usage, costs, caching, and thread patterns.
|
|
5
5
|
Author: Douglas Monsky
|
|
6
6
|
License-Expression: MIT
|
|
@@ -190,6 +190,34 @@ The tracker cannot read your logged-in ChatGPT plan or live remaining usage auto
|
|
|
190
190
|
- Companion Codex skills for operational setup and conversational usage analysis.
|
|
191
191
|
- Optional local pricing, Codex credit, allowance, threshold, project alias, and privacy-mode configuration.
|
|
192
192
|
|
|
193
|
+
## Dashboard Language
|
|
194
|
+
|
|
195
|
+
The dashboard supports localized UI text. English is the canonical catalog, and the project includes starter locale catalogs for common dashboard languages.
|
|
196
|
+
|
|
197
|
+
Set the initial dashboard language with `--lang`:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
codex-usage-tracker --lang vi serve-dashboard --open
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Or set a default with:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
CODEX_USAGE_TRACKER_LANG=vi codex-usage-tracker serve-dashboard --open
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The dashboard also includes a language selector. Browser selections are stored locally and can override the generated default for that browser.
|
|
210
|
+
|
|
211
|
+
Supported starter locales include English, Vietnamese, Spanish, French, German, Portuguese, Japanese, Simplified Chinese, Korean, Russian, Italian, and Arabic. This localizes dashboard UI text, not the full CLI output or data exports.
|
|
212
|
+
|
|
213
|
+
### Adding A Dashboard Language
|
|
214
|
+
|
|
215
|
+
1. Add a locale JSON file named by language code under `src/codex_usage_tracker/plugin_data/dashboard/locales/`.
|
|
216
|
+
2. Include every key from the English catalog.
|
|
217
|
+
3. Preserve every placeholder from the English string.
|
|
218
|
+
4. Add the language code, native name, English name, and text direction to the supported language metadata.
|
|
219
|
+
5. Run the i18n validation tests.
|
|
220
|
+
|
|
193
221
|
## Common Commands
|
|
194
222
|
|
|
195
223
|
```bash
|
|
@@ -153,6 +153,34 @@ The tracker cannot read your logged-in ChatGPT plan or live remaining usage auto
|
|
|
153
153
|
- Companion Codex skills for operational setup and conversational usage analysis.
|
|
154
154
|
- Optional local pricing, Codex credit, allowance, threshold, project alias, and privacy-mode configuration.
|
|
155
155
|
|
|
156
|
+
## Dashboard Language
|
|
157
|
+
|
|
158
|
+
The dashboard supports localized UI text. English is the canonical catalog, and the project includes starter locale catalogs for common dashboard languages.
|
|
159
|
+
|
|
160
|
+
Set the initial dashboard language with `--lang`:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
codex-usage-tracker --lang vi serve-dashboard --open
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Or set a default with:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
CODEX_USAGE_TRACKER_LANG=vi codex-usage-tracker serve-dashboard --open
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The dashboard also includes a language selector. Browser selections are stored locally and can override the generated default for that browser.
|
|
173
|
+
|
|
174
|
+
Supported starter locales include English, Vietnamese, Spanish, French, German, Portuguese, Japanese, Simplified Chinese, Korean, Russian, Italian, and Arabic. This localizes dashboard UI text, not the full CLI output or data exports.
|
|
175
|
+
|
|
176
|
+
### Adding A Dashboard Language
|
|
177
|
+
|
|
178
|
+
1. Add a locale JSON file named by language code under `src/codex_usage_tracker/plugin_data/dashboard/locales/`.
|
|
179
|
+
2. Include every key from the English catalog.
|
|
180
|
+
3. Preserve every placeholder from the English string.
|
|
181
|
+
4. Add the language code, native name, English name, and text direction to the supported language metadata.
|
|
182
|
+
5. Run the i18n validation tests.
|
|
183
|
+
|
|
156
184
|
## Common Commands
|
|
157
185
|
|
|
158
186
|
```bash
|
|
@@ -83,6 +83,8 @@ codex-usage-tracker serve-dashboard --no-context-api --open
|
|
|
83
83
|
|
|
84
84
|
Dashboards default to active sessions only. Use `--include-archived` for an all-history static/opened dashboard, or switch the served dashboard's `History` control from `Active sessions only` to `All history` when you intentionally want archived logs scanned and included.
|
|
85
85
|
|
|
86
|
+
Use global `--lang <code>` before the dashboard command, or set `CODEX_USAGE_TRACKER_LANG`, to choose the dashboard's initial UI language. The dashboard language selector can then override that default in the browser. Localization applies to dashboard UI text, not JSON fields, CSV columns, model names, thread names, paths, or full CLI output.
|
|
87
|
+
|
|
86
88
|
The localhost `/api/usage` endpoint accepts `limit` and `offset` query parameters, so automation can page aggregate rows without asking the server to load an entire large history at once.
|
|
87
89
|
|
|
88
90
|
## Summaries
|
|
@@ -37,6 +37,15 @@ Redacted mode hides raw cwd/source paths, hides Git remote labels, and hashes un
|
|
|
37
37
|
|
|
38
38
|
`serve-dashboard` refreshes active-session logs before opening by default. Use `--no-refresh` only when you intentionally want a cached view of the existing local index.
|
|
39
39
|
|
|
40
|
+
Set the initial dashboard language with the global `--lang` option before the command, or use `CODEX_USAGE_TRACKER_LANG`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
codex-usage-tracker --lang vi serve-dashboard --open
|
|
44
|
+
CODEX_USAGE_TRACKER_LANG=vi codex-usage-tracker serve-dashboard --open
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The dashboard language selector stores your browser preference locally. It localizes dashboard UI labels, captions, badges, empty states, detail-panel labels, context controls, and recommendation text; it does not translate raw data values, JSON fields, CSV columns, model names, thread names, project names, paths, or full CLI output.
|
|
48
|
+
|
|
40
49
|
The server keeps the HTML aggregate-only and enables two live features:
|
|
41
50
|
|
|
42
51
|
- `Refresh` rescans local Codex logs and updates the dashboard rows.
|
|
@@ -38,7 +38,7 @@ fix/<issue-number>-short-description
|
|
|
38
38
|
docs/<issue-number>-short-description
|
|
39
39
|
chore/<issue-number>-short-description
|
|
40
40
|
test/<issue-number>-short-description
|
|
41
|
-
release/0.
|
|
41
|
+
release/0.5.0
|
|
42
42
|
hotfix/0.3.3
|
|
43
43
|
```
|
|
44
44
|
|
|
@@ -91,7 +91,7 @@ blocked
|
|
|
91
91
|
Recommended milestones:
|
|
92
92
|
|
|
93
93
|
```text
|
|
94
|
-
0.
|
|
94
|
+
0.5.0
|
|
95
95
|
1.0-readiness
|
|
96
96
|
1.0.0
|
|
97
97
|
```
|
|
@@ -147,10 +147,12 @@ python scripts/smoke_installed_package.py --docker
|
|
|
147
147
|
To verify the public PyPI package instead of the local checkout:
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
|
-
python scripts/smoke_installed_package.py --from-pypi --version 0.
|
|
151
|
-
python scripts/smoke_installed_package.py --docker --from-pypi --version 0.
|
|
150
|
+
python scripts/smoke_installed_package.py --from-pypi --version 0.5.0
|
|
151
|
+
python scripts/smoke_installed_package.py --docker --from-pypi --version 0.5.0
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
+
`scripts/check_release.py` treats these public-package smoke commands as release-state claims. Keep their `--version` and `codex-usage-tracking==...` values aligned with `pyproject.toml`; the release gate fails when the docs claim a different public version. It also checks that install docs point at the real PyPI distribution, `codex-usage-tracking`, and keep the warning that `codex-usage-tracker` is a different PyPI package.
|
|
155
|
+
|
|
154
156
|
Docker avoids local toolchain side effects during install testing. Keep one local `pipx` smoke for platform-specific PATH and plugin-discovery behavior, but use Docker for repeatable Linux package verification.
|
|
155
157
|
|
|
156
158
|
For documentation-only branches, at minimum run:
|
|
@@ -222,7 +224,7 @@ Tracked timings:
|
|
|
222
224
|
| `pricing_coverage_seconds` | Pricing coverage report |
|
|
223
225
|
| `project_summary_seconds` | Project summary report |
|
|
224
226
|
|
|
225
|
-
The normal CI smoke uses a tiny synthetic history with `--enforce-thresholds` so
|
|
227
|
+
The normal CI smoke uses a tiny synthetic history with `--enforce-thresholds` and a small `--threshold-scale` allowance so coverage instrumentation and shared runner noise do not create false failures. The 10k/100k runs are a practical local gate for performance-sensitive changes; the 500k run is the release-sized gate and can take about a minute on a modern laptop because recommendations and project summary intentionally scan all aggregate rows.
|
|
226
228
|
|
|
227
229
|
## Release Checklist
|
|
228
230
|
|
|
@@ -264,8 +266,8 @@ After the release branch merges, tag from updated `main`, not from an unreviewed
|
|
|
264
266
|
```bash
|
|
265
267
|
git switch main
|
|
266
268
|
git pull --ff-only
|
|
267
|
-
git tag -a v0.
|
|
268
|
-
git push origin v0.
|
|
269
|
+
git tag -a v0.5.0 -m "codex-usage-tracker 0.5.0"
|
|
270
|
+
git push origin v0.5.0
|
|
269
271
|
```
|
|
270
272
|
|
|
271
273
|
Do not create or push release tags without maintainer approval.
|
|
@@ -274,13 +276,12 @@ Do not create or push release tags without maintainer approval.
|
|
|
274
276
|
|
|
275
277
|
Publishing uses GitHub Actions Trusted Publishing through `.github/workflows/publish.yml`; do not upload from a local machine and do not add PyPI or TestPyPI API tokens.
|
|
276
278
|
|
|
277
|
-
The first public package release, `0.3.0`, was published on June 8, 2026. Patch release `0.3.1` followed the same day to ship the live-dashboard skill launch fix. Patch release `0.3.2` made dashboard launch refresh the default and added runtime enablement for context loading. Minor release `0.4.0` added Python 3.14 support, release recovery docs, stricter privacy/support-bundle regression coverage, and large-history benchmark thresholds. Patch release `0.4.1` hardened the PyPI publish workflow and checked off completed 1.0 readiness gates
|
|
279
|
+
The first public package release, `0.3.0`, was published on June 8, 2026. Patch release `0.3.1` followed the same day to ship the live-dashboard skill launch fix. Patch release `0.3.2` made dashboard launch refresh the default and added runtime enablement for context loading. Minor release `0.4.0` added Python 3.14 support, release recovery docs, stricter privacy/support-bundle regression coverage, and large-history benchmark thresholds. Patch release `0.4.1` was published by workflow dispatch from `main`; it hardened the PyPI publish workflow and checked off completed 1.0 readiness gates. Minor release `0.5.0` added dashboard localization support and starter language catalogs.
|
|
278
280
|
|
|
279
281
|
- GitHub Release: `https://github.com/douglasmonsky/codex-usage-tracker/releases/tag/v0.3.0`
|
|
280
282
|
- GitHub Release: `https://github.com/douglasmonsky/codex-usage-tracker/releases/tag/v0.3.1`
|
|
281
283
|
- GitHub Release: `https://github.com/douglasmonsky/codex-usage-tracker/releases/tag/v0.3.2`
|
|
282
284
|
- GitHub Release: `https://github.com/douglasmonsky/codex-usage-tracker/releases/tag/v0.4.0`
|
|
283
|
-
- GitHub Release: `https://github.com/douglasmonsky/codex-usage-tracker/releases/tag/v0.4.1`
|
|
284
285
|
- PyPI: `https://pypi.org/project/codex-usage-tracking/`
|
|
285
286
|
- TestPyPI: `https://test.pypi.org/project/codex-usage-tracking/`
|
|
286
287
|
|
|
@@ -24,12 +24,12 @@ Not guaranteed:
|
|
|
24
24
|
|
|
25
25
|
## 1. Public Install And Package Metadata
|
|
26
26
|
|
|
27
|
-
- [x] Verify the current public PyPI version is visible as `0.
|
|
28
|
-
- [x] Verify public venv install for `0.
|
|
29
|
-
- [x] Verify public pipx install path for `0.
|
|
27
|
+
- [x] Verify the current public PyPI version is visible as `0.5.0`: `python -c "import json, urllib.request; print(json.load(urllib.request.urlopen('https://pypi.org/pypi/codex-usage-tracking/json'))['info']['version'])"`.
|
|
28
|
+
- [x] Verify public venv install for `0.5.0`: `python -m venv /tmp/codex-usage-pypi-smoke && . /tmp/codex-usage-pypi-smoke/bin/activate && python -m pip install codex-usage-tracking==0.5.0 && codex-usage-tracker --version`.
|
|
29
|
+
- [x] Verify public pipx install path for `0.5.0`: `PIPX_HOME=/tmp/codex-usage-pipx-home PIPX_BIN_DIR=/tmp/codex-usage-pipx-bin pipx install codex-usage-tracking==0.5.0 && /tmp/codex-usage-pipx-bin/codex-usage-tracker --version`.
|
|
30
30
|
- [x] Verify installed package resources from a built wheel: `python scripts/smoke_installed_package.py`.
|
|
31
31
|
- [x] Verify installed package resources in Linux Docker: `python scripts/smoke_installed_package.py --docker`.
|
|
32
|
-
- [x] Verify public PyPI package in Docker: `python scripts/smoke_installed_package.py --docker --from-pypi --version 0.
|
|
32
|
+
- [x] Verify public PyPI package in Docker: `python scripts/smoke_installed_package.py --docker --from-pypi --version 0.5.0`.
|
|
33
33
|
- [x] Verify PyPI metadata names remain unchanged: `python scripts/check_release.py`.
|
|
34
34
|
- [x] Add Python 3.14 as an official support target after CI, package classifiers, docs, and installed-package smoke coverage were added. Docker smoke coverage uses `python:3.14-slim` by default. Track this in issue #12.
|
|
35
35
|
|
|
@@ -120,8 +120,8 @@ Not guaranteed:
|
|
|
120
120
|
- [x] Verify manual PyPI workflow dispatch is restricted to `main` or tag refs: `python scripts/check_release.py`.
|
|
121
121
|
- [x] Verify PyPI job is gated by environment `pypi`: `gh api repos/douglasmonsky/codex-usage-tracker/environments/pypi`.
|
|
122
122
|
- [x] Verify dist filenames match `codex_usage_tracking`: `python -m build && python scripts/check_release.py --dist`.
|
|
123
|
-
- [
|
|
124
|
-
- [
|
|
123
|
+
- [x] Verify TestPyPI process: run `Publish Python package` with `target=testpypi` only when intentionally testing release publication.
|
|
124
|
+
- [x] Verify PyPI process: publish a GitHub Release or run workflow dispatch with `target=pypi` only when intentionally publishing a reviewed release.
|
|
125
125
|
- [x] Document release recovery by cutting a new patch version when an uploaded artifact is wrong: see `docs/development.md`.
|
|
126
126
|
|
|
127
127
|
## 13. Known Limitations
|
|
@@ -134,14 +134,14 @@ Not guaranteed:
|
|
|
134
134
|
|
|
135
135
|
## Evidence References
|
|
136
136
|
|
|
137
|
-
These references are the concrete proof behind completed checklist items. Public package smoke commands are version-specific to `0.
|
|
137
|
+
These references are the concrete proof behind completed checklist items. Public package smoke commands are version-specific to `0.5.0`; all repo tests use synthetic or aggregate-only data.
|
|
138
138
|
|
|
139
139
|
### Public Install And Package Metadata
|
|
140
140
|
|
|
141
141
|
- Public PyPI version, public venv install, and public pipx install are proven by the exact public-install commands in section 1.
|
|
142
142
|
- Built-wheel and installed-resource coverage is proven by `scripts/smoke_installed_package.py` and `tests/test_cli_release.py::test_installed_package_smoke_checks_help_for_stable_commands`.
|
|
143
143
|
- Linux package-resource coverage is proven by `scripts/smoke_installed_package.py --docker`.
|
|
144
|
-
- Public PyPI Docker coverage is proven by `scripts/smoke_installed_package.py --docker --from-pypi --version 0.
|
|
144
|
+
- Public PyPI Docker coverage is proven by `scripts/smoke_installed_package.py --docker --from-pypi --version 0.5.0`.
|
|
145
145
|
- PyPI metadata, package/distribution names, package resources, source/wheel member names, Python 3.10-3.14 support metadata, CI workflow requirements, publish workflow safety text, and tracked secret patterns are proven by `scripts/check_release.py`, `scripts/check_release.py --dist`, and `tests/test_cli_release.py::test_release_check_script_passes`.
|
|
146
146
|
|
|
147
147
|
### Upgrade And Migration
|
|
@@ -211,7 +211,7 @@ These references are the concrete proof behind completed checklist items. Public
|
|
|
211
211
|
|
|
212
212
|
- Benchmark command behavior and threshold contract are smoke-tested by `tests/test_cli_release.py::test_synthetic_history_benchmark_script_smoke`.
|
|
213
213
|
- Release-size 10k, 100k, and 500k benchmark claims are proven by running `python scripts/benchmark_synthetic_history.py --rows 10000 100000 500000 --json --enforce-thresholds` before release work when practical.
|
|
214
|
-
- CI-safe benchmark coverage is proven by the CI `Release readiness` job through `tests/test_cli_release.py::test_synthetic_history_benchmark_script_smoke
|
|
214
|
+
- CI-safe benchmark coverage is proven by the CI `Release readiness` job through `tests/test_cli_release.py::test_synthetic_history_benchmark_script_smoke`, using a small `--threshold-scale` allowance for coverage instrumentation and shared runner noise.
|
|
215
215
|
|
|
216
216
|
### Release Process
|
|
217
217
|
|
|
@@ -219,6 +219,8 @@ These references are the concrete proof behind completed checklist items. Public
|
|
|
219
219
|
- Publish workflow package name, Trusted Publishing, TestPyPI/PyPI job presence, event guards, no push/PR publishing, no token/password publishing, and manual PyPI main/tag preflight are proven by `scripts/check_release.py::_check_publish_workflow`.
|
|
220
220
|
- The GitHub `pypi` environment gate is proven by `gh api repos/douglasmonsky/codex-usage-tracker/environments/pypi`, which reports a `required_reviewers` protection rule and `can_admins_bypass=false`.
|
|
221
221
|
- Dist filename and wheel/sdist member checks are proven by `python -m build`, `python -m twine check dist/*`, and `python scripts/check_release.py --dist`.
|
|
222
|
+
- TestPyPI publish process is proven by a workflow-dispatch run on `main`, followed by TestPyPI metadata and clean virtualenv install checks for `codex-usage-tracking==0.5.0`.
|
|
223
|
+
- PyPI publish process is proven by a workflow-dispatch run on `main`, protected `pypi` environment approval, PyPI metadata visibility, clean virtualenv install, temporary pipx install, and Docker public-package smoke for `codex-usage-tracking==0.5.0`.
|
|
222
224
|
- Release recovery documentation is proven by `scripts/check_release.py` required-file and docs checks.
|
|
223
225
|
|
|
224
226
|
### Known Limitations
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codex-usage-tracking"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0"
|
|
8
8
|
description = "Unofficial local Codex plugin and dashboard for investigating aggregate token usage, costs, caching, and thread patterns."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -62,6 +62,7 @@ where = ["src"]
|
|
|
62
62
|
"codex_usage_tracker.plugin_data" = [
|
|
63
63
|
"assets/*",
|
|
64
64
|
"dashboard/*",
|
|
65
|
+
"dashboard/locales/*",
|
|
65
66
|
"docs/*",
|
|
66
67
|
"docs/assets/*",
|
|
67
68
|
"rate_cards/*",
|
|
@@ -23,6 +23,43 @@ DIST_FILE_STEM = "codex_usage_tracking"
|
|
|
23
23
|
IMPORT_PACKAGE = "codex_usage_tracker"
|
|
24
24
|
CONSOLE_SCRIPT = "codex-usage-tracker"
|
|
25
25
|
SUPPORTED_PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
26
|
+
OLD_PYPI_DISTRIBUTION_NAME = "codex-usage-tracker"
|
|
27
|
+
DASHBOARD_LOCALE_CODES = [
|
|
28
|
+
"en",
|
|
29
|
+
"vi",
|
|
30
|
+
"es",
|
|
31
|
+
"fr",
|
|
32
|
+
"de",
|
|
33
|
+
"pt",
|
|
34
|
+
"ja",
|
|
35
|
+
"zh-Hans",
|
|
36
|
+
"ko",
|
|
37
|
+
"ru",
|
|
38
|
+
"it",
|
|
39
|
+
"ar",
|
|
40
|
+
]
|
|
41
|
+
DASHBOARD_LOCALE_SOURCE_FILES = [
|
|
42
|
+
f"src/codex_usage_tracker/plugin_data/dashboard/locales/{code}.json"
|
|
43
|
+
for code in DASHBOARD_LOCALE_CODES
|
|
44
|
+
]
|
|
45
|
+
DASHBOARD_LOCALE_WHEEL_MEMBERS = {
|
|
46
|
+
f"codex_usage_tracker/plugin_data/dashboard/locales/{code}.json"
|
|
47
|
+
for code in DASHBOARD_LOCALE_CODES
|
|
48
|
+
}
|
|
49
|
+
PUBLIC_RELEASE_DOCS = [
|
|
50
|
+
"docs/one-dot-oh-readiness.md",
|
|
51
|
+
"docs/development.md",
|
|
52
|
+
]
|
|
53
|
+
PACKAGE_NAMING_DOCS = [
|
|
54
|
+
"README.md",
|
|
55
|
+
"docs/install.md",
|
|
56
|
+
"docs/development.md",
|
|
57
|
+
]
|
|
58
|
+
PUBLIC_VERSION_PATTERNS = [
|
|
59
|
+
re.compile(r"codex-usage-tracking==([0-9]+(?:\.[0-9]+){2})"),
|
|
60
|
+
re.compile(r"--from-pypi --version ([0-9]+(?:\.[0-9]+){2})"),
|
|
61
|
+
re.compile(r"visible as `([0-9]+(?:\.[0-9]+){2})`"),
|
|
62
|
+
]
|
|
26
63
|
SECRET_PATTERNS = {
|
|
27
64
|
"OpenAI API key": re.compile(r"\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}"),
|
|
28
65
|
"GitHub token": re.compile(r"\b(?:ghp|github_pat)_[A-Za-z0-9_]{20,}"),
|
|
@@ -62,6 +99,7 @@ REQUIRED_FILES = [
|
|
|
62
99
|
"src/codex_usage_tracker/plugin_data/dashboard/dashboard.js",
|
|
63
100
|
"src/codex_usage_tracker/plugin_data/dashboard/dashboard_state.js",
|
|
64
101
|
"src/codex_usage_tracker/plugin_data/dashboard/dashboard_template.html",
|
|
102
|
+
*DASHBOARD_LOCALE_SOURCE_FILES,
|
|
65
103
|
"src/codex_usage_tracker/plugin_data/docs/dashboard-guide.html",
|
|
66
104
|
"src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json",
|
|
67
105
|
"src/codex_usage_tracker/plugin_data/docs/assets/dashboard-insights.png",
|
|
@@ -79,6 +117,7 @@ WHEEL_REQUIRED_MEMBERS = {
|
|
|
79
117
|
"codex_usage_tracker/plugin_data/dashboard/dashboard.js",
|
|
80
118
|
"codex_usage_tracker/plugin_data/dashboard/dashboard_state.js",
|
|
81
119
|
"codex_usage_tracker/plugin_data/dashboard/dashboard_template.html",
|
|
120
|
+
*DASHBOARD_LOCALE_WHEEL_MEMBERS,
|
|
82
121
|
"codex_usage_tracker/plugin_data/docs/dashboard-guide.html",
|
|
83
122
|
"codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json",
|
|
84
123
|
"codex_usage_tracker/plugin_data/docs/assets/dashboard-insights.png",
|
|
@@ -156,6 +195,7 @@ def _check_versions() -> list[str]:
|
|
|
156
195
|
failures.append(".codex-plugin/plugin.json version does not match pyproject.toml")
|
|
157
196
|
if f"## {package_version}" not in changelog:
|
|
158
197
|
failures.append("CHANGELOG.md does not contain an entry for the package version")
|
|
198
|
+
failures.extend(_check_public_release_doc_versions(package_version))
|
|
159
199
|
return failures
|
|
160
200
|
|
|
161
201
|
|
|
@@ -164,6 +204,7 @@ def _check_docs() -> list[str]:
|
|
|
164
204
|
failures: list[str] = []
|
|
165
205
|
for required in [
|
|
166
206
|
"pipx install",
|
|
207
|
+
"codex-usage-tracking",
|
|
167
208
|
"codex-usage-tracker install-plugin",
|
|
168
209
|
"codex-usage-tracker doctor",
|
|
169
210
|
"Data Privacy",
|
|
@@ -171,6 +212,57 @@ def _check_docs() -> list[str]:
|
|
|
171
212
|
]:
|
|
172
213
|
if required not in readme:
|
|
173
214
|
failures.append(f"README.md is missing required install/privacy text: {required}")
|
|
215
|
+
failures.extend(_check_package_naming_docs())
|
|
216
|
+
return failures
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _check_public_release_doc_versions(package_version: str) -> list[str]:
|
|
220
|
+
failures: list[str] = []
|
|
221
|
+
for relative_path in PUBLIC_RELEASE_DOCS:
|
|
222
|
+
path = REPO_ROOT / relative_path
|
|
223
|
+
text = path.read_text(encoding="utf-8")
|
|
224
|
+
for pattern in PUBLIC_VERSION_PATTERNS:
|
|
225
|
+
for match in pattern.finditer(text):
|
|
226
|
+
if match.group(1) != package_version:
|
|
227
|
+
failures.append(
|
|
228
|
+
f"{relative_path} public release version {match.group(1)} "
|
|
229
|
+
f"does not match pyproject.toml {package_version}"
|
|
230
|
+
)
|
|
231
|
+
return failures
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _check_package_naming_docs() -> list[str]:
|
|
235
|
+
failures: list[str] = []
|
|
236
|
+
old_name_warning = f"The `{OLD_PYPI_DISTRIBUTION_NAME}` PyPI name is not this project"
|
|
237
|
+
for relative_path in PACKAGE_NAMING_DOCS:
|
|
238
|
+
text = (REPO_ROOT / relative_path).read_text(encoding="utf-8")
|
|
239
|
+
if DISTRIBUTION_NAME not in text:
|
|
240
|
+
failures.append(f"{relative_path} must name the public PyPI package {DISTRIBUTION_NAME}")
|
|
241
|
+
if relative_path in {"README.md", "docs/install.md"} and old_name_warning not in text:
|
|
242
|
+
failures.append(
|
|
243
|
+
f"{relative_path} must warn that {OLD_PYPI_DISTRIBUTION_NAME} "
|
|
244
|
+
"is a different PyPI package"
|
|
245
|
+
)
|
|
246
|
+
failures.extend(_check_doc_install_lines(relative_path, text))
|
|
247
|
+
return failures
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _check_doc_install_lines(relative_path: str, text: str) -> list[str]:
|
|
251
|
+
failures: list[str] = []
|
|
252
|
+
for line_number, line in enumerate(text.splitlines(), start=1):
|
|
253
|
+
normalized = line.strip().strip("`")
|
|
254
|
+
if not normalized:
|
|
255
|
+
continue
|
|
256
|
+
if not re.search(r"\b(?:pipx|pip|python(?:3)? -m pip)\s+install\b", normalized):
|
|
257
|
+
continue
|
|
258
|
+
if OLD_PYPI_DISTRIBUTION_NAME not in normalized:
|
|
259
|
+
continue
|
|
260
|
+
if DISTRIBUTION_NAME in normalized or "git+" in normalized or "github.com" in normalized:
|
|
261
|
+
continue
|
|
262
|
+
failures.append(
|
|
263
|
+
f"{relative_path}:{line_number} installs {OLD_PYPI_DISTRIBUTION_NAME}; "
|
|
264
|
+
f"use {DISTRIBUTION_NAME}"
|
|
265
|
+
)
|
|
174
266
|
return failures
|
|
175
267
|
|
|
176
268
|
|
|
@@ -322,6 +414,8 @@ def _check_publish_workflow() -> list[str]:
|
|
|
322
414
|
"name: pypi",
|
|
323
415
|
"https://test.pypi.org/project/codex-usage-tracking/",
|
|
324
416
|
"https://pypi.org/project/codex-usage-tracking/",
|
|
417
|
+
"steps.package-version.outputs.exists != 'true'",
|
|
418
|
+
"codex-usage-tracking {version} already exists on {index_name}; skipping upload.",
|
|
325
419
|
]:
|
|
326
420
|
if required not in workflow:
|
|
327
421
|
failures.append(f"publish workflow is missing required Trusted Publishing text: {required}")
|
|
@@ -343,6 +437,11 @@ def _check_publish_workflow() -> list[str]:
|
|
|
343
437
|
"echo \"sha=$GITHUB_SHA\"",
|
|
344
438
|
"refs/heads/main|refs/tags/*",
|
|
345
439
|
"Manual PyPI publishing must run from main or a tag ref.",
|
|
440
|
+
"Check target package version",
|
|
441
|
+
"id: package-version",
|
|
442
|
+
"PACKAGE_INDEX_JSON_URL",
|
|
443
|
+
"PACKAGE_INDEX_NAME",
|
|
444
|
+
"steps.package-version.outputs.exists != 'true'",
|
|
346
445
|
]:
|
|
347
446
|
if required not in job_block:
|
|
348
447
|
failures.append(f"publish workflow {job_name} job is missing preflight: {required}")
|
|
@@ -376,27 +475,12 @@ def _check_ci_workflow() -> list[str]:
|
|
|
376
475
|
return failures
|
|
377
476
|
|
|
378
477
|
|
|
379
|
-
def _check_ci_workflow() -> list[str]:
|
|
380
|
-
workflow_path = REPO_ROOT / ".github" / "workflows" / "ci.yml"
|
|
381
|
-
if not workflow_path.exists():
|
|
382
|
-
return ["missing CI workflow: .github/workflows/ci.yml"]
|
|
383
|
-
workflow = workflow_path.read_text(encoding="utf-8")
|
|
384
|
-
failures: list[str] = []
|
|
385
|
-
for required in [
|
|
386
|
-
"name: Build package",
|
|
387
|
-
"python -m build",
|
|
388
|
-
"python -m twine check dist/*",
|
|
389
|
-
"python scripts/check_release.py --dist",
|
|
390
|
-
]:
|
|
391
|
-
if required not in workflow:
|
|
392
|
-
failures.append(f"CI package job is missing required build check: {required}")
|
|
393
|
-
return failures
|
|
394
|
-
|
|
395
|
-
|
|
396
478
|
def _check_skill_packaging() -> list[str]:
|
|
397
479
|
failures: list[str] = []
|
|
398
480
|
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
|
|
399
481
|
package_data = set(pyproject["tool"]["setuptools"]["package-data"]["codex_usage_tracker.plugin_data"])
|
|
482
|
+
if "dashboard/locales/*" not in package_data:
|
|
483
|
+
failures.append("pyproject.toml package data is missing dashboard locale catalogs")
|
|
400
484
|
for source_skill in sorted((REPO_ROOT / "skills").glob("*/SKILL.md")):
|
|
401
485
|
skill_name = source_skill.parent.name
|
|
402
486
|
package_skill = (
|
{codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/scripts/smoke_installed_package.py
RENAMED
|
@@ -73,6 +73,18 @@ RESOURCE_PATHS = [
|
|
|
73
73
|
"dashboard/dashboard.js",
|
|
74
74
|
"dashboard/dashboard_state.js",
|
|
75
75
|
"dashboard/dashboard_template.html",
|
|
76
|
+
"dashboard/locales/en.json",
|
|
77
|
+
"dashboard/locales/vi.json",
|
|
78
|
+
"dashboard/locales/es.json",
|
|
79
|
+
"dashboard/locales/fr.json",
|
|
80
|
+
"dashboard/locales/de.json",
|
|
81
|
+
"dashboard/locales/pt.json",
|
|
82
|
+
"dashboard/locales/ja.json",
|
|
83
|
+
"dashboard/locales/zh-Hans.json",
|
|
84
|
+
"dashboard/locales/ko.json",
|
|
85
|
+
"dashboard/locales/ru.json",
|
|
86
|
+
"dashboard/locales/it.json",
|
|
87
|
+
"dashboard/locales/ar.json",
|
|
76
88
|
"docs/dashboard-guide.html",
|
|
77
89
|
"docs/assets/dashboard-insights.png",
|
|
78
90
|
"docs/assets/dashboard-calls.png",
|
|
@@ -15,9 +15,9 @@ from pathlib import Path
|
|
|
15
15
|
|
|
16
16
|
PACKAGE_SPEC = os.environ.get(
|
|
17
17
|
"CODEX_USAGE_TRACKER_PACKAGE_SPEC",
|
|
18
|
-
"codex-usage-tracking==0.
|
|
18
|
+
"codex-usage-tracking==0.5.0",
|
|
19
19
|
)
|
|
20
|
-
RUNTIME_VERSION = "0.
|
|
20
|
+
RUNTIME_VERSION = "0.5.0"
|
|
21
21
|
PACKAGE_SPEC_MARKER = ".codex-usage-tracker-package-spec"
|
|
22
22
|
MODULE_CHECK = (
|
|
23
23
|
"import importlib.metadata; "
|
|
@@ -30,6 +30,7 @@ from codex_usage_tracker.formatting import (
|
|
|
30
30
|
format_doctor,
|
|
31
31
|
format_session,
|
|
32
32
|
)
|
|
33
|
+
from codex_usage_tracker.i18n import normalize_language
|
|
33
34
|
from codex_usage_tracker.parser import inspect_log, load_session_index
|
|
34
35
|
from codex_usage_tracker.paths import (
|
|
35
36
|
DEFAULT_ALLOWANCE_PATH,
|
|
@@ -110,6 +111,14 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
110
111
|
parser.add_argument("--rate-card", type=Path, default=DEFAULT_RATE_CARD_PATH)
|
|
111
112
|
parser.add_argument("--thresholds", type=Path, default=DEFAULT_THRESHOLDS_PATH)
|
|
112
113
|
parser.add_argument("--projects", type=Path, default=DEFAULT_PROJECTS_PATH)
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
"--lang",
|
|
116
|
+
default=None,
|
|
117
|
+
help=(
|
|
118
|
+
"Initial dashboard language. Accepts supported language codes and common aliases; "
|
|
119
|
+
"defaults to CODEX_USAGE_TRACKER_LANG or en."
|
|
120
|
+
),
|
|
121
|
+
)
|
|
113
122
|
parser.add_argument(
|
|
114
123
|
"--privacy-mode",
|
|
115
124
|
choices=PRIVACY_MODE_CHOICES,
|
|
@@ -942,6 +951,7 @@ def _run_dashboard(args: argparse.Namespace) -> int:
|
|
|
942
951
|
projects_path=args.projects,
|
|
943
952
|
privacy_mode=args.privacy_mode,
|
|
944
953
|
include_archived=args.include_archived,
|
|
954
|
+
language=normalize_language(args.lang),
|
|
945
955
|
)
|
|
946
956
|
if args.as_json:
|
|
947
957
|
_print_json(
|
|
@@ -954,6 +964,7 @@ def _run_dashboard(args: argparse.Namespace) -> int:
|
|
|
954
964
|
"since": args.since,
|
|
955
965
|
"privacy_mode": args.privacy_mode,
|
|
956
966
|
"include_archived": args.include_archived,
|
|
967
|
+
"language": normalize_language(args.lang),
|
|
957
968
|
}
|
|
958
969
|
)
|
|
959
970
|
else:
|
|
@@ -986,6 +997,7 @@ def _run_open_dashboard(args: argparse.Namespace) -> int:
|
|
|
986
997
|
projects_path=args.projects,
|
|
987
998
|
privacy_mode=args.privacy_mode,
|
|
988
999
|
include_archived=args.include_archived,
|
|
1000
|
+
language=normalize_language(args.lang),
|
|
989
1001
|
)
|
|
990
1002
|
if args.as_json:
|
|
991
1003
|
_print_json(
|
|
@@ -999,6 +1011,7 @@ def _run_open_dashboard(args: argparse.Namespace) -> int:
|
|
|
999
1011
|
"refresh": refresh_payload,
|
|
1000
1012
|
"privacy_mode": args.privacy_mode,
|
|
1001
1013
|
"include_archived": args.include_archived,
|
|
1014
|
+
"language": normalize_language(args.lang),
|
|
1002
1015
|
}
|
|
1003
1016
|
)
|
|
1004
1017
|
else:
|
|
@@ -1021,6 +1034,7 @@ def _run_serve_dashboard(args: argparse.Namespace) -> int:
|
|
|
1021
1034
|
"refresh_before_start": args.refresh,
|
|
1022
1035
|
"privacy_mode": args.privacy_mode,
|
|
1023
1036
|
"include_archived": args.include_archived,
|
|
1037
|
+
"language": normalize_language(args.lang),
|
|
1024
1038
|
}
|
|
1025
1039
|
)
|
|
1026
1040
|
if args.refresh:
|
|
@@ -1047,6 +1061,7 @@ def _run_serve_dashboard(args: argparse.Namespace) -> int:
|
|
|
1047
1061
|
thresholds_path=args.thresholds,
|
|
1048
1062
|
projects_path=args.projects,
|
|
1049
1063
|
privacy_mode=args.privacy_mode,
|
|
1064
|
+
language=normalize_language(args.lang),
|
|
1050
1065
|
)
|
|
1051
1066
|
return 0
|
|
1052
1067
|
|
{codex_usage_tracking-0.4.1 → codex_usage_tracking-0.5.0}/src/codex_usage_tracker/costing.py
RENAMED
|
@@ -8,6 +8,15 @@ from typing import Any
|
|
|
8
8
|
from codex_usage_tracker.paths import DEFAULT_PRICING_PATH
|
|
9
9
|
from codex_usage_tracker.pricing_config import PricingConfig, load_pricing_config
|
|
10
10
|
|
|
11
|
+
EFFICIENCY_FLAG_KEYS = {
|
|
12
|
+
"high context use": "flag.high_context_use",
|
|
13
|
+
"elevated context use": "flag.elevated_context_use",
|
|
14
|
+
"high reasoning share": "flag.high_reasoning_share",
|
|
15
|
+
"low cache reuse": "flag.low_cache_reuse",
|
|
16
|
+
"expensive low-output call": "flag.expensive_low_output_call",
|
|
17
|
+
"high estimated cost": "flag.high_estimated_cost",
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
|
|
12
21
|
def summarize_pricing_coverage(
|
|
13
22
|
rows: list[dict[str, Any]],
|
|
@@ -92,6 +101,11 @@ def annotate_rows_with_efficiency(
|
|
|
92
101
|
copy["pricing_model"] = config.priced_as(model)
|
|
93
102
|
copy["pricing_estimated"] = config.is_estimated_model(model)
|
|
94
103
|
copy["efficiency_flags"] = efficiency_flags(copy)
|
|
104
|
+
copy["efficiency_flag_keys"] = [
|
|
105
|
+
EFFICIENCY_FLAG_KEYS[flag]
|
|
106
|
+
for flag in copy["efficiency_flags"]
|
|
107
|
+
if flag in EFFICIENCY_FLAG_KEYS
|
|
108
|
+
]
|
|
95
109
|
annotated.append(copy)
|
|
96
110
|
return annotated
|
|
97
111
|
|