copilot-session-usage 0.2.1__tar.gz → 0.2.3__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.
Files changed (107) hide show
  1. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/CHANGELOG.md +6 -0
  2. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/PKG-INFO +3 -3
  3. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/README.md +2 -2
  4. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/conf.py +5 -0
  5. copilot_session_usage-0.2.3/docs/source/explanation/how-cost-estimation-works.md +138 -0
  6. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/index.md +4 -0
  7. copilot_session_usage-0.2.3/docs/source/reference/pricing.md +122 -0
  8. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/tutorials/getting-started.md +24 -11
  9. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/justfile +1 -0
  10. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/_schema/Base.schema.yaml +10 -1
  11. copilot_session_usage-0.2.3/knowledge/_schema/Experiment.schema.yaml +44 -0
  12. copilot_session_usage-0.2.3/knowledge/_schema/Finding.schema.yaml +49 -0
  13. copilot_session_usage-0.2.3/knowledge/_schema/Principle.schema.yaml +25 -0
  14. copilot_session_usage-0.2.3/knowledge/_schema/Structure.schema.yaml +26 -0
  15. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/concepts/overview.md +2 -2
  16. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/concepts/session-cost-analysis.md +1 -1
  17. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/experiments/verify-subagent-cost-attribution.md +2 -1
  18. copilot_session_usage-0.2.3/knowledge/findings/cache-write-cost-not-tracked.md +83 -0
  19. copilot_session_usage-0.2.3/knowledge/findings/index.md +7 -0
  20. copilot_session_usage-0.2.3/knowledge/findings/title-jsonl-not-counted-as-model-turn.md +50 -0
  21. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/reference/debug-log-format.md +3 -2
  22. copilot_session_usage-0.2.3/knowledge/structures/cache-cost-approximation.md +86 -0
  23. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/structures/index.md +1 -0
  24. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/structures/subagent-cost-tracking.md +13 -5
  25. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/structures/vscode-copilot-extension.md +9 -1
  26. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/_internal/core.py +53 -14
  27. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/_internal/vscode.py +54 -0
  28. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/api.py +7 -1
  29. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/cli.py +5 -0
  30. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/data/custom-models-pricing.yml +3 -2
  31. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/conftest.py +4 -6
  32. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_api.py +100 -109
  33. copilot_session_usage-0.2.3/tests/test_cli.py +280 -0
  34. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_coverage_gaps.py +32 -33
  35. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_vscode.py +42 -0
  36. copilot_session_usage-0.2.1/docs/source/explanation/how-cost-estimation-works.md +0 -96
  37. copilot_session_usage-0.2.1/docs/source/reference/pricing.md +0 -62
  38. copilot_session_usage-0.2.1/knowledge/_schema/Experiment.schema.yaml +0 -55
  39. copilot_session_usage-0.2.1/knowledge/_schema/Finding.schema.yaml +0 -64
  40. copilot_session_usage-0.2.1/knowledge/_schema/Principle.schema.yaml +0 -40
  41. copilot_session_usage-0.2.1/knowledge/_schema/Structure.schema.yaml +0 -41
  42. copilot_session_usage-0.2.1/knowledge/findings/index.md +0 -5
  43. copilot_session_usage-0.2.1/tests/test_cli.py +0 -274
  44. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.editorconfig +0 -0
  45. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  46. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  47. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/guidelines/knowledge-base.guidelines.md +0 -0
  48. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/pull_request_template.md +0 -0
  49. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/skills/consolidate-knowledge-base/SKILL.md +0 -0
  50. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/skills/record-finding/SKILL.md +0 -0
  51. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/workflows/ci.yml +0 -0
  52. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.github/workflows/publish.yml +0 -0
  53. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.gitignore +0 -0
  54. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/.readthedocs.yaml +0 -0
  55. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/AGENTS.md +0 -0
  56. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/CONTRIBUTING.md +0 -0
  57. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/LICENSE +0 -0
  58. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/_static/changelog.js +0 -0
  59. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/_static/custom.css +0 -0
  60. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/changelog.md +0 -0
  61. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/explanation/index.md +0 -0
  62. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/how-to/analyze-specific-session.md +0 -0
  63. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/how-to/batch-and-spending.md +0 -0
  64. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/how-to/export-json.md +0 -0
  65. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/how-to/index.md +0 -0
  66. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/how-to/wsl2.md +0 -0
  67. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/installation.md +0 -0
  68. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/reference/api.md +0 -0
  69. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/reference/cli.md +0 -0
  70. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/reference/index.md +0 -0
  71. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/docs/source/tutorials/index.md +0 -0
  72. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/_schema/Concept.schema.yaml +0 -0
  73. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/_schema/Playbook.schema.yaml +0 -0
  74. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/_schema/Reference.schema.yaml +0 -0
  75. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/concepts/copilot-cli.md +0 -0
  76. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/concepts/index.md +0 -0
  77. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/concepts/threshold-based-pricing.md +0 -0
  78. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/experiments/index.md +0 -0
  79. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/findings/subagent-logs-use-runsubagent-prefix.md +0 -0
  80. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/guides/automation-scripts.md +0 -0
  81. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/guides/cost-optimization.md +0 -0
  82. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/guides/index.md +0 -0
  83. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/guides/wsl2-setup.md +0 -0
  84. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/ideas/index.md +0 -0
  85. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/ideas/multi-session-efficiency-analytics.md +0 -0
  86. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/index.md +0 -0
  87. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/log.md +0 -0
  88. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/principles/findings-are-immutable.md +0 -0
  89. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/principles/index.md +0 -0
  90. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/reference/index.md +0 -0
  91. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/reference/pricing-formats.md +0 -0
  92. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/structures/knowledge-base-information-types.md +0 -0
  93. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/knowledge/structures/session-discovery-algorithm.md +0 -0
  94. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/pyproject.toml +0 -0
  95. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/scripts/refresh_pricing.py +0 -0
  96. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/skills/copilot-session-usage/SKILL.md +0 -0
  97. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/__init__.py +0 -0
  98. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/_internal/__init__.py +0 -0
  99. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/_internal/copilot_cli.py +0 -0
  100. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/data/__init__.py +0 -0
  101. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/data/models-and-pricing.lock +0 -0
  102. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/src/copilot_session_usage/data/models-and-pricing.yml +0 -0
  103. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_core.py +0 -0
  104. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_rendering.py +0 -0
  105. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/tests/test_vscode_platform.py +0 -0
  106. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/uv.lock +0 -0
  107. {copilot_session_usage-0.2.1 → copilot_session_usage-0.2.3}/uv.toml +0 -0
@@ -1,5 +1,11 @@
1
1
  ## Unreleased
2
2
 
3
+ ### Feat
4
+
5
+ - accurate AIC cost computation using nanoAiu and cache_write
6
+
7
+ ## v0.2.1 (2026-07-02)
8
+
3
9
  ## v0.2.0 (2026-07-02)
4
10
 
5
11
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copilot-session-usage
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Usage and cost analytics for GitHub Copilot and Copilot-CLI session logs
5
5
  Project-URL: Homepage, https://github.com/gsemet/copilot-session-usage
6
6
  Project-URL: Documentation, https://copilot-session-usage.readthedocs.io/en/stable/
@@ -27,6 +27,8 @@ Description-Content-Type: text/markdown
27
27
 
28
28
  Extract VS Code Copilot session cost KPIs (tokens, estimated USD, model, duration) from local debug logs.
29
29
 
30
+ **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/en/stable/)
31
+
30
32
  ## Installation
31
33
 
32
34
  ```bash
@@ -183,8 +185,6 @@ just docs
183
185
  just docs-serve
184
186
  ```
185
187
 
186
- **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/)
187
-
188
188
  ## License
189
189
 
190
190
  MIT — see [LICENSE](LICENSE).
@@ -11,6 +11,8 @@
11
11
 
12
12
  Extract VS Code Copilot session cost KPIs (tokens, estimated USD, model, duration) from local debug logs.
13
13
 
14
+ **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/en/stable/)
15
+
14
16
  ## Installation
15
17
 
16
18
  ```bash
@@ -167,8 +169,6 @@ just docs
167
169
  just docs-serve
168
170
  ```
169
171
 
170
- **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/)
171
-
172
172
  ## License
173
173
 
174
174
  MIT — see [LICENSE](LICENSE).
@@ -24,6 +24,11 @@ extensions = [
24
24
  myst_enable_extensions = ["colon_fence", "deflist"]
25
25
 
26
26
  html_theme = "furo"
27
+ html_theme_options = {
28
+ "source_repository": "https://github.com/gsemet/copilot-session-usage",
29
+ "source_branch": "main",
30
+ "source_directory": "docs/source/",
31
+ }
27
32
  html_title = f"copilot-session-usage {version}"
28
33
  html_static_path = ["_static"]
29
34
  html_css_files = ["custom.css"]
@@ -0,0 +1,138 @@
1
+ # How Cost Estimation Works
2
+
3
+ `copilot-session-usage` estimates session costs from VS Code debug logs.
4
+ This page explains each step.
5
+
6
+ ---
7
+
8
+ ## Where the logs live
9
+
10
+ VS Code stores one directory per workspace under `workspaceStorage`. Inside
11
+ each workspace directory, the Copilot extension writes debug logs:
12
+
13
+ ```
14
+ workspaceStorage/
15
+ └── <workspace-hash>/
16
+ └── GitHub.copilot-chat/
17
+ └── debug-logs/
18
+ └── <session-uuid>/
19
+ ├── *.jsonl ← token events
20
+ └── ...
21
+ ```
22
+
23
+ Default locations by platform:
24
+
25
+ | Platform | Path |
26
+ |----------|------|
27
+ | macOS | `~/Library/Application Support/Code/User/workspaceStorage/` |
28
+ | Linux | `~/.config/Code/User/workspaceStorage/` |
29
+ | Windows | `%APPDATA%\Code\User\workspaceStorage\` |
30
+ | WSL2 (remote) | `~/.vscode-server/data/User/workspaceStorage/` |
31
+
32
+ The tool also checks `Code - Insiders` variants automatically.
33
+
34
+ ---
35
+
36
+ ## How sessions are discovered
37
+
38
+ The tool reads the session title from VS Code's SQLite workspace database
39
+ (`state.vscdb`). Sessions are sorted by the last-modified time of their
40
+ debug-log directory, most recent first.
41
+
42
+ The `list` command reads only metadata (no JSONL parsing). The `analyze`,
43
+ `id`, and `batch` commands parse the full JSONL files.
44
+
45
+ ---
46
+
47
+ ## Parsing JSONL logs
48
+
49
+ Each `.jsonl` file contains one JSON object per line. The tool extracts
50
+ token-count events emitted by the Copilot extension for each LLM call:
51
+
52
+ - `input_tokens` — tokens sent to the model
53
+ - `output_tokens` — tokens generated by the model
54
+ - `cached_tokens` — input tokens served from the provider's prompt cache
55
+ - `model` — the model name as reported by the provider
56
+
57
+ A single session may call multiple models (e.g., Claude Sonnet for the main
58
+ request and Claude Haiku for a subagent). Each model's tokens are summed
59
+ separately, then costs are computed per model and aggregated.
60
+
61
+ ---
62
+
63
+ ## Cost calculation
64
+
65
+ The VS Code debug log reports `inputTokens` as the **total** prompt sent
66
+ (cached + non-cached combined). `cachedTokens` is the subset served from
67
+ the provider's cache. The non-cached portion is `inputTokens − cachedTokens`.
68
+
69
+ Each `llm_request` event also carries `copilotUsageNanoAiu` — VS Code's own
70
+ cost for that call in nano-AI Credits (nanoAIU). It is present for all
71
+ Copilot-plan models (Claude, GPT, and others). It is absent for Azure-hosted
72
+ models not billed via Copilot AIC — `Kimi-K2.6-azure` is one such model:
73
+ it is billed through Azure separately and correctly reports $0 AIC.
74
+
75
+ When `copilotUsageNanoAiu` is present and non-zero, the tool uses it directly:
76
+
77
+ ```
78
+ cost_usd = copilotUsageNanoAiu / 100_000_000_000 (1 nanoAIU = 1e-11 USD)
79
+ ```
80
+
81
+ For models that do not report `copilotUsageNanoAiu` — Azure-hosted models billed
82
+ outside the Copilot plan — the tool falls back to token-based computation
83
+ (or $0 when the model has no Copilot pricing entry):
84
+
85
+ ```
86
+ cost_usd = (
87
+ (inputTokens - cachedTokens) × rate.input # fresh tokens
88
+ + cachedTokens × rate.cached_input # cache-read tokens
89
+ + outputTokens × rate.output
90
+ ) / 1_000_000
91
+ ```
92
+
93
+ plus the Anthropic cache-write approximation when applicable.
94
+
95
+ Verified on a real session: `copilotUsageNanoAiu`-based cost matches the
96
+ VS Code AIC panel at **0.000% error** for Claude models.
97
+
98
+ ---
99
+
100
+ ## Subagent attribution
101
+
102
+ `runSubagent` calls appear in the JSONL as a distinct event type. The tool
103
+ tracks them separately so `--detail full` can show which fraction of tokens
104
+ was consumed by subagents vs. the main conversation.
105
+
106
+ ---
107
+
108
+ ## Accuracy
109
+
110
+ For Copilot-plan models (Claude, GPT, etc.), the tool reads
111
+ `copilotUsageNanoAiu` — VS Code's own per-call cost field — directly from the
112
+ JSONL, so the session total matches the VS Code AIC panel at **0% error**.
113
+
114
+ For Azure-hosted models billed outside the Copilot plan (`Kimi-K2.6-azure` is
115
+ the current example), `copilotUsageNanoAiu` is absent. The tool falls back to
116
+ token-based pricing using rates in `custom-models-pricing.yml`. These models
117
+ are billed through Azure separately; setting their prices to `$0.00` in
118
+ `custom-models-pricing.yml` correctly reflects that they do not consume AIC.
119
+
120
+ ### Why the LLM-call count differs by 1 from the panel
121
+
122
+ The VS Code Agent Debug panel excludes the `title-*.jsonl` file (background
123
+ title-generation calls). `copilot-session-usage` counts them because they
124
+ consume real tokens. A session with one title-generation call will show one
125
+ more LLM call and the corresponding (small) token counts compared to the panel.
126
+
127
+ ### Why token counts can differ between tool and panel
128
+
129
+ Token counts in the tool include `title-*.jsonl`; the VS Code panel does not.
130
+ For session `438d24a8`, the delta is exactly one Kimi call: +441 input, +1,245
131
+ output.
132
+
133
+ ### Pricing table updates
134
+
135
+ The bundled pricing table (`data/models-and-pricing.yml`) is updated with each
136
+ release. Run `just refresh-pricing` to pull the latest rates. Stale rates only
137
+ affect the token-based fallback path; `copilotUsageNanoAiu`-based costs are
138
+ unaffected by the table.
@@ -1,5 +1,7 @@
1
1
  # copilot-session-usage
2
2
 
3
+ [![GitHub](https://img.shields.io/badge/GitHub-copilot--session--usage-181717?logo=github)](https://github.com/gsemet/copilot-session-usage)
4
+
3
5
  **copilot-session-usage** reads VS Code Copilot debug logs and tells you
4
6
  how much each AI coding session cost in USD.
5
7
 
@@ -11,6 +13,8 @@ prints a cost report in seconds.
11
13
  The most common use: after a heavy agentic session, run
12
14
  `copilot-session-usage latest` to see what it cost.
13
15
 
16
+ Links to source code: [gsemet/copilot-session-usage](https://github.com/gsemet/copilot-session-usage)
17
+
14
18
  ::::{grid} 1 1 2 2
15
19
  :gutter: 3
16
20
 
@@ -0,0 +1,122 @@
1
+ # Pricing Reference
2
+
3
+ `copilot-session-usage` ships a bundled pricing table at
4
+ `src/copilot_session_usage/data/models-and-pricing.yml`.
5
+
6
+ ## Upstream source
7
+
8
+ Prices are synced from the GitHub Copilot official rate card:
9
+ [`github/docs` — `data/tables/copilot/models-and-pricing.yml`](https://github.com/github/docs/blob/main/data/tables/copilot/models-and-pricing.yml)
10
+
11
+ The bundled copy is updated with each release.
12
+
13
+ ## Cost formula
14
+
15
+ The VS Code debug log reports three token counts per LLM call:
16
+
17
+ | Field in log | Meaning |
18
+ |---|---|
19
+ | `inputTokens` | **Total** prompt tokens sent — cached and non-cached combined |
20
+ | `cachedTokens` | Subset of `inputTokens` served from the provider's prompt cache |
21
+ | `outputTokens` | Completion tokens generated |
22
+
23
+ Non-cached input = `inputTokens − cachedTokens`. The two input
24
+ components are billed at different rates, so the formula splits them:
25
+
26
+ ```
27
+ cost_usd = (
28
+ (inputTokens - cachedTokens) × rate.input # fresh prompt tokens
29
+ + cachedTokens × rate.cached_input # cache-read tokens
30
+ + outputTokens × rate.output # completion tokens
31
+ ) / 1_000_000
32
+ ```
33
+
34
+ Results are summed across all models called in the session.
35
+
36
+ The equivalent statement using Anthropic-style variable names
37
+ (where `input` already excludes cached tokens) is:
38
+
39
+ ```
40
+ cost_usd = (
41
+ input × rate.input
42
+ + cache_read × rate.cached_input
43
+ + cache_creation × (rate.cache_write ?? rate.input)
44
+ + output × rate.output
45
+ ) / 1_000_000
46
+ ```
47
+
48
+ VS Code debug logs do not expose `cache_creation` tokens directly.
49
+ For Anthropic models, the tool approximates the incremental cache-creation
50
+ cost using fresh input as a proxy (see note below).
51
+
52
+ :::{note}
53
+ **Anthropic `cache_write` — approximated via fresh input.**
54
+
55
+ Anthropic models have a `cache_write` rate for tokens written to the provider's
56
+ cache for the first time. VS Code JSONL logs do not expose `cacheCreationTokens`;
57
+ `agent-traces.db` has the schema column but VS Code does not populate it for
58
+ Claude models (verified: 0 rows, VS Code 1.103+).
59
+
60
+ The tool approximates the incremental cost as:
61
+
62
+ ```
63
+ delta = (inputTokens - cachedTokens) × (cache_write_per_m - input_per_m) / 1_000_000
64
+ ```
65
+
66
+ Verified on a real 92-call Claude Sonnet 4.6 session: this matches the VS Code
67
+ AIC panel exactly ($5.9037 both ways). Models without `cache_write` (OpenAI,
68
+ Google) are unaffected — the delta is zero.
69
+
70
+ `agent_traces_db_paths()` in `vscode.py` locates `agent-traces.db` on all
71
+ platforms. When VS Code starts populating `gen_ai.usage.cache_creation.input_tokens`,
72
+ reading the exact value from the DB will replace this proxy without API changes.
73
+ :::
74
+
75
+ ## AI Credits and USD
76
+
77
+ Post-2026-06-01, GitHub Copilot bills in **AI Credits (AIC)**.
78
+ The upstream rate card publishes prices in USD per million tokens.
79
+ The conversion is:
80
+
81
+ ```
82
+ 1 AIC = $0.01 USD → 100 AIC = $1.00 USD
83
+ ```
84
+
85
+ A model priced at `input: $3.00` per million tokens costs **300 AIC**
86
+ per million input tokens. This tool reports USD; multiply by 100 to get AIC.
87
+
88
+ The per-token AIC rate is identical across all Copilot plans. Plans differ
89
+ only in the monthly AIC allowance included — that allowance is not tracked
90
+ by this tool.
91
+
92
+ ## Cache discounts
93
+
94
+ All providers discount tokens served from their prompt cache:
95
+
96
+ | Provider | Cache-read discount vs. input |
97
+ |----------|-------------------------------|
98
+ | OpenAI | ~10× cheaper |
99
+ | Anthropic | ~10× cheaper |
100
+ | Google | ~10× cheaper |
101
+
102
+ A session with 85% cache hit ratio costs significantly less than raw
103
+ token counts suggest.
104
+
105
+ ## Long-context tier switching
106
+
107
+ Some models have two pricing tiers based on input token count:
108
+
109
+ | Model | Threshold | Effect |
110
+ |-------|-----------|--------|
111
+ | GPT-5.4 | > 272K tokens | Input/cached/output prices double |
112
+ | GPT-5.5 | > 272K tokens | Input/cached/output prices double |
113
+ | Gemini 3.1 Pro | > 200K tokens | Input/cached/output prices increase |
114
+
115
+ `copilot-session-usage` selects the correct tier automatically based on
116
+ the session's total input tokens per model.
117
+
118
+ ## Custom pricing
119
+
120
+ Override any model's price by editing
121
+ `src/copilot_session_usage/data/custom-models-pricing.yml`. Entries in
122
+ this file take precedence over the main table.
@@ -11,7 +11,7 @@ output. It assumes you have installed `copilot-session-usage` — see
11
11
  Run this after any VS Code Copilot chat session:
12
12
 
13
13
  ```bash
14
- copilot-session-usage latest
14
+ copilot-session-usage latest --format table
15
15
  ```
16
16
 
17
17
  Sample output:
@@ -41,19 +41,16 @@ Each field:
41
41
 
42
42
  ---
43
43
 
44
- ## Switch detail levels
44
+ ## Details Tables
45
45
 
46
- `--detail` controls how much data is shown:
46
+ `--format` controls the output type. Default is `json`:
47
47
 
48
48
  ```bash
49
49
  # Just cost and model names
50
- copilot-session-usage latest --detail minimal
50
+ copilot-session-usage latest --format table
51
51
 
52
- # Default: summary + per-model breakdown
53
- copilot-session-usage latest --detail compact
54
-
55
- # Everything: per-model + subagent attribution
56
- copilot-session-usage latest --detail full
52
+ # Default: summary + per-subagent breakdown
53
+ copilot-session-usage latest --format detailed
57
54
  ```
58
55
 
59
56
  ---
@@ -76,10 +73,16 @@ copilot-session-usage latest --format json --output session.json
76
73
 
77
74
  ## List recent sessions
78
75
 
79
- See which sessions exist without computing costs:
76
+ See which sessions exist without computing costs (limit set to 20 by default):
80
77
 
81
78
  ```bash
82
79
  copilot-session-usage list
80
+
81
+ # Limit to 5 sessions
82
+ copilot-session-usage list --limit 5
83
+
84
+ # Since a date
85
+ copilot-session-usage list --since 2026-07-01
83
86
  ```
84
87
 
85
88
  Output:
@@ -106,7 +109,14 @@ it lists them so you can pick the right UUID.
106
109
  ## Analyze a specific session by UUID
107
110
 
108
111
  ```bash
112
+ # Default json output
109
113
  copilot-session-usage id f5cbde8a-ec40-466f-86e6-f95c343b6c58
114
+
115
+ # Human readable summary
116
+ copilot-session-usage id f5cbde8a-ec40-466f-86e6-f95c343b6c58 --format table
117
+
118
+ # Human readable details with per-subagent breakdown
119
+ copilot-session-usage id f5cbde8a-ec40-466f-86e6-f95c343b6c58 --format detailed
110
120
  ```
111
121
 
112
122
  ---
@@ -114,8 +124,11 @@ copilot-session-usage id f5cbde8a-ec40-466f-86e6-f95c343b6c58
114
124
  ## Analyze multiple sessions at once
115
125
 
116
126
  ```bash
117
- # Last 10 sessions
127
+ # Last 10 sessions (json output)
118
128
  copilot-session-usage batch 10
129
+
130
+ # Summary table for last 10 sessions
131
+ copilot-session-usage batch 10 --format table
119
132
  ```
120
133
 
121
134
  Output includes a summary row with aggregate totals and a per-session table.
@@ -116,6 +116,7 @@ preflight:
116
116
  just typecheck
117
117
  just tests-coverage
118
118
  just knowledge-lint
119
+ just knowledge-validate
119
120
  just docs
120
121
 
121
122
  # ─── Cleanup ──────────────────────────────────────────────────────────────────
@@ -23,4 +23,13 @@ properties:
23
23
  description: ISO 8601 creation or last-updated timestamp.
24
24
  type: string
25
25
  format: date-time
26
- additionalProperties: false
26
+ links:
27
+ type: array
28
+ items:
29
+ type: string
30
+ description: "Bundle-relative paths this concept links to"
31
+ backlinks:
32
+ type: array
33
+ items:
34
+ type: string
35
+ description: "Bundle-relative paths of concepts that link to this one"
@@ -0,0 +1,44 @@
1
+ $schema: "http://json-schema.org/draft-07/schema#"
2
+ title: Experiment
3
+ description: >-
4
+ A reusable, prepared procedure that can be executed one or two times to test a
5
+ hypothesis. Each execution produces one Finding. The Experiment is a template;
6
+ its recorded outcomes live as Finding documents.
7
+ allOf:
8
+ - $ref: "Base.schema.yaml"
9
+ - type: object
10
+ properties:
11
+ type:
12
+ description: Document type — must be "Experiment".
13
+ type: string
14
+ const: Experiment
15
+ hypothesis:
16
+ description: The claim the experiment is designed to confirm or falsify.
17
+ type: string
18
+ minLength: 1
19
+ steps:
20
+ description: Ordered procedure to run the experiment reproducibly.
21
+ type: array
22
+ items: { type: string }
23
+ minItems: 1
24
+ expected_signals:
25
+ description: Observable signals that indicate the hypothesis holds or fails.
26
+ type: array
27
+ items: { type: string }
28
+ max_runs:
29
+ description: How many times this experiment is meant to be run (typically 1–2).
30
+ type: integer
31
+ minimum: 1
32
+ status:
33
+ description: Lifecycle state of the experiment template.
34
+ type: string
35
+ enum: [proposed, active, retired, superseded]
36
+ derived_findings:
37
+ description: IDs of Findings produced by running this experiment.
38
+ type: array
39
+ items: { type: string }
40
+ superseded_by:
41
+ description: IDs of documents that supersede this experiment.
42
+ type: array
43
+ items: { type: string }
44
+ required: [type, hypothesis, steps]
@@ -0,0 +1,49 @@
1
+ $schema: "http://json-schema.org/draft-07/schema#"
2
+ title: Finding
3
+ description: >-
4
+ An empirical, dated, falsifiable record of what an agent or human truthfully
5
+ observed and believed at a point in time. The body is immutable once written;
6
+ only lifecycle frontmatter (status, contradicted_by, superseded_by) may be
7
+ appended later.
8
+ allOf:
9
+ - $ref: "Base.schema.yaml"
10
+ - type: object
11
+ properties:
12
+ type:
13
+ description: Document type — must be "Finding".
14
+ type: string
15
+ const: Finding
16
+ confidence:
17
+ description: How confident the reporter was at the time of recording.
18
+ type: string
19
+ enum: [low, medium, high, confirmed]
20
+ context:
21
+ description: >-
22
+ What the reporter believed and the situation at the time — the honest
23
+ basis for the finding, including assumptions that may later prove wrong.
24
+ type: string
25
+ minLength: 1
26
+ status:
27
+ description: Lifecycle state. Appended non-destructively; the body never changes.
28
+ type: string
29
+ enum: [active, contradicted, superseded]
30
+ derived_from:
31
+ description: ID of the Experiment whose run produced this finding, if any.
32
+ type: string
33
+ contradicts:
34
+ description: IDs of earlier Findings this finding contradicts.
35
+ type: array
36
+ items: { type: string }
37
+ supersedes:
38
+ description: IDs of earlier Findings this finding replaces.
39
+ type: array
40
+ items: { type: string }
41
+ contradicted_by:
42
+ description: IDs of later Findings that contradict this one (appended by review).
43
+ type: array
44
+ items: { type: string }
45
+ superseded_by:
46
+ description: IDs of later Findings that replace this one (appended by review).
47
+ type: array
48
+ items: { type: string }
49
+ required: [type, timestamp, confidence, context]
@@ -0,0 +1,25 @@
1
+ $schema: "http://json-schema.org/draft-07/schema#"
2
+ title: Principle
3
+ description: >-
4
+ A standard or convention, usually defined with humans. Principles are stable,
5
+ normative statements ("we always…", "never…") — not dated observations. They
6
+ may be supported by Findings but are agreed, not merely observed.
7
+ allOf:
8
+ - $ref: "Base.schema.yaml"
9
+ - type: object
10
+ properties:
11
+ type:
12
+ description: Document type — must be "Principle".
13
+ type: string
14
+ const: Principle
15
+ rationale:
16
+ description: Why this principle exists and what it protects against.
17
+ type: string
18
+ authority:
19
+ description: Who agreed this principle (e.g. "team", "human-reviewed").
20
+ type: string
21
+ supported_by:
22
+ description: IDs of Findings that provide empirical support for this principle.
23
+ type: array
24
+ items: { type: string }
25
+ required: [type]
@@ -0,0 +1,26 @@
1
+ $schema: "http://json-schema.org/draft-07/schema#"
2
+ title: Structure
3
+ description: >-
4
+ A description of how an object, system, or artifact is composed and how its
5
+ parts relate — the "how it works" view. Distinct from a Concept (an idea) and
6
+ from a Playbook (a procedure to perform).
7
+ allOf:
8
+ - $ref: "Base.schema.yaml"
9
+ - type: object
10
+ properties:
11
+ type:
12
+ description: Document type — must be "Structure".
13
+ type: string
14
+ const: Structure
15
+ subject:
16
+ description: The object or system whose structure is described.
17
+ type: string
18
+ parts:
19
+ description: The components, fields, or sub-parts that make up the subject.
20
+ type: array
21
+ items: { type: string }
22
+ related_concepts:
23
+ description: IDs of Concept documents that explain the ideas behind this structure.
24
+ type: array
25
+ items: { type: string }
26
+ required: [type]
@@ -19,9 +19,9 @@ Every LLM request made by a coding agent (parent or subagent) is logged as a str
19
19
 
20
20
  | Metric | Source Field | Description |
21
21
  |--------|-------------|-------------|
22
- | Input Tokens | `attrs.inputTokens` | Tokens sent to the model (prompt + context) |
22
+ | Input Tokens | `attrs.inputTokens` | **Total** prompt tokens sent (cached + non-cached) |
23
23
  | Output Tokens | `attrs.outputTokens` | Tokens generated by the model |
24
- | Cached Tokens | `attrs.cachedTokens` | Prompt tokens served from cache (not billed) |
24
+ | Cached Tokens | `attrs.cachedTokens` | Subset of input tokens served from the provider's prompt cache (billed at a lower rate) |
25
25
  | LLM Calls | Count of `llm_request` events | Number of individual model invocations |
26
26
  | Model | `attrs.model` | Which model handled the request |
27
27
 
@@ -6,7 +6,7 @@ description: Process of extracting token usage metrics from Copilot debug logs
6
6
  tags: [cost-analysis, tokens, pricing, debug-logs]
7
7
  timestamp: 2026-06-30T22:00:00Z
8
8
  links: []
9
- backlinks: []
9
+ backlinks: [structures/cache-cost-approximation.md]
10
10
  ---
11
11
 
12
12
  # Session Cost Analysis
@@ -18,7 +18,8 @@ steps: [Pick a session directory that contains at least one runSubagent-*.jsonl
18
18
  expected_signals: ['Tool total equals independent sum (no double-count, no omission).',
19
19
  Each subagent subtotal is attributed to its own runSubagent id.]
20
20
  max_runs: 2
21
- status: proposed
21
+ status: superseded
22
+ superseded_by: [structures/subagent-cost-tracking.md]
22
23
  links: []
23
24
  backlinks: []
24
25
  ---