copilot-session-usage 0.1.0__tar.gz → 0.2.1__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 (104) hide show
  1. copilot_session_usage-0.2.1/.github/guidelines/knowledge-base.guidelines.md +86 -0
  2. copilot_session_usage-0.2.1/.github/skills/consolidate-knowledge-base/SKILL.md +68 -0
  3. copilot_session_usage-0.2.1/.github/skills/record-finding/SKILL.md +62 -0
  4. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.github/workflows/ci.yml +1 -0
  5. copilot_session_usage-0.2.1/.readthedocs.yaml +24 -0
  6. copilot_session_usage-0.2.1/CHANGELOG.md +13 -0
  7. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/PKG-INFO +5 -2
  8. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/README.md +3 -0
  9. copilot_session_usage-0.2.1/docs/source/_static/changelog.js +25 -0
  10. copilot_session_usage-0.2.1/docs/source/_static/custom.css +142 -0
  11. copilot_session_usage-0.2.1/docs/source/changelog.md +4 -0
  12. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/docs/source/conf.py +4 -0
  13. copilot_session_usage-0.2.1/docs/source/explanation/how-cost-estimation-works.md +96 -0
  14. copilot_session_usage-0.2.1/docs/source/explanation/index.md +9 -0
  15. copilot_session_usage-0.2.1/docs/source/how-to/analyze-specific-session.md +46 -0
  16. copilot_session_usage-0.2.1/docs/source/how-to/batch-and-spending.md +64 -0
  17. copilot_session_usage-0.2.1/docs/source/how-to/export-json.md +65 -0
  18. copilot_session_usage-0.2.1/docs/source/how-to/index.md +12 -0
  19. copilot_session_usage-0.2.1/docs/source/how-to/wsl2.md +37 -0
  20. copilot_session_usage-0.2.1/docs/source/index.md +66 -0
  21. copilot_session_usage-0.2.1/docs/source/installation.md +42 -0
  22. copilot_session_usage-0.2.1/docs/source/reference/api.md +18 -0
  23. copilot_session_usage-0.2.1/docs/source/reference/index.md +11 -0
  24. copilot_session_usage-0.2.1/docs/source/reference/pricing.md +62 -0
  25. copilot_session_usage-0.2.1/docs/source/tutorials/getting-started.md +129 -0
  26. copilot_session_usage-0.2.1/docs/source/tutorials/index.md +9 -0
  27. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/justfile +21 -3
  28. copilot_session_usage-0.1.0/knowledge/_schema/Concept.schema.yaml → copilot_session_usage-0.2.1/knowledge/_schema/Base.schema.yaml +5 -6
  29. copilot_session_usage-0.2.1/knowledge/_schema/Concept.schema.yaml +20 -0
  30. copilot_session_usage-0.2.1/knowledge/_schema/Experiment.schema.yaml +55 -0
  31. copilot_session_usage-0.2.1/knowledge/_schema/Finding.schema.yaml +64 -0
  32. copilot_session_usage-0.2.1/knowledge/_schema/Playbook.schema.yaml +19 -0
  33. copilot_session_usage-0.2.1/knowledge/_schema/Principle.schema.yaml +40 -0
  34. copilot_session_usage-0.2.1/knowledge/_schema/Reference.schema.yaml +19 -0
  35. copilot_session_usage-0.2.1/knowledge/_schema/Structure.schema.yaml +41 -0
  36. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/concepts/copilot-cli.md +4 -1
  37. copilot_session_usage-0.2.1/knowledge/concepts/index.md +8 -0
  38. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/concepts/overview.md +4 -2
  39. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/concepts/session-cost-analysis.md +3 -1
  40. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/concepts/threshold-based-pricing.md +3 -1
  41. copilot_session_usage-0.2.1/knowledge/experiments/index.md +5 -0
  42. copilot_session_usage-0.2.1/knowledge/experiments/verify-subagent-cost-attribution.md +31 -0
  43. copilot_session_usage-0.2.1/knowledge/findings/index.md +5 -0
  44. copilot_session_usage-0.2.1/knowledge/findings/subagent-logs-use-runsubagent-prefix.md +38 -0
  45. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/guides/automation-scripts.md +4 -2
  46. {copilot_session_usage-0.1.0/knowledge/concepts → copilot_session_usage-0.2.1/knowledge/guides}/cost-optimization.md +4 -2
  47. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/guides/index.md +4 -1
  48. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/guides/wsl2-setup.md +3 -1
  49. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/ideas/index.md +3 -1
  50. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/ideas/multi-session-efficiency-analytics.md +3 -1
  51. copilot_session_usage-0.2.1/knowledge/index.md +16 -0
  52. copilot_session_usage-0.2.1/knowledge/principles/findings-are-immutable.md +40 -0
  53. copilot_session_usage-0.2.1/knowledge/principles/index.md +5 -0
  54. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/reference/debug-log-format.md +8 -3
  55. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/reference/index.md +3 -1
  56. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/reference/pricing-formats.md +3 -1
  57. copilot_session_usage-0.2.1/knowledge/structures/index.md +8 -0
  58. copilot_session_usage-0.2.1/knowledge/structures/knowledge-base-information-types.md +42 -0
  59. {copilot_session_usage-0.1.0/knowledge/concepts → copilot_session_usage-0.2.1/knowledge/structures}/session-discovery-algorithm.md +4 -2
  60. {copilot_session_usage-0.1.0/knowledge/concepts → copilot_session_usage-0.2.1/knowledge/structures}/subagent-cost-tracking.md +5 -2
  61. {copilot_session_usage-0.1.0/knowledge/concepts → copilot_session_usage-0.2.1/knowledge/structures}/vscode-copilot-extension.md +6 -3
  62. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/pyproject.toml +16 -3
  63. copilot_session_usage-0.2.1/scripts/refresh_pricing.py +9 -0
  64. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/_internal/core.py +117 -3
  65. copilot_session_usage-0.2.1/src/copilot_session_usage/data/models-and-pricing.lock +7 -0
  66. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/data/models-and-pricing.yml +9 -0
  67. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_core.py +23 -0
  68. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/uv.lock +343 -98
  69. copilot_session_usage-0.1.0/.github/guidelines/knowledge-base.guidelines.md +0 -105
  70. copilot_session_usage-0.1.0/docs/source/api.md +0 -19
  71. copilot_session_usage-0.1.0/docs/source/index.md +0 -40
  72. copilot_session_usage-0.1.0/knowledge/_schema/Playbook.schema.yaml +0 -27
  73. copilot_session_usage-0.1.0/knowledge/_schema/Reference.schema.yaml +0 -27
  74. copilot_session_usage-0.1.0/knowledge/concepts/index.md +0 -10
  75. copilot_session_usage-0.1.0/knowledge/index.md +0 -10
  76. copilot_session_usage-0.1.0/src/copilot_session_usage/data/models-and-pricing.lock +0 -7
  77. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.editorconfig +0 -0
  78. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  79. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  80. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.github/pull_request_template.md +0 -0
  81. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.github/workflows/publish.yml +0 -0
  82. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/.gitignore +0 -0
  83. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/AGENTS.md +0 -0
  84. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/CONTRIBUTING.md +0 -0
  85. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/LICENSE +0 -0
  86. {copilot_session_usage-0.1.0/docs/source → copilot_session_usage-0.2.1/docs/source/reference}/cli.md +0 -0
  87. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/knowledge/log.md +0 -0
  88. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/skills/copilot-session-usage/SKILL.md +0 -0
  89. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/__init__.py +0 -0
  90. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/_internal/__init__.py +0 -0
  91. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/_internal/copilot_cli.py +0 -0
  92. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/_internal/vscode.py +0 -0
  93. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/api.py +0 -0
  94. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/cli.py +0 -0
  95. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/data/__init__.py +0 -0
  96. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/src/copilot_session_usage/data/custom-models-pricing.yml +0 -0
  97. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/conftest.py +0 -0
  98. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_api.py +0 -0
  99. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_cli.py +0 -0
  100. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_coverage_gaps.py +0 -0
  101. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_rendering.py +0 -0
  102. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_vscode.py +0 -0
  103. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/tests/test_vscode_platform.py +0 -0
  104. {copilot_session_usage-0.1.0 → copilot_session_usage-0.2.1}/uv.toml +0 -0
@@ -0,0 +1,86 @@
1
+ ---
2
+ applyTo: "knowledge/**/*.md"
3
+ description: "The minimal rules a coding agent must follow to maintain the OKF knowledge bundle in knowledge/."
4
+ ---
5
+
6
+ # Knowledge Base Maintenance Guidelines
7
+
8
+ `knowledge/` is an [OKF](https://github.com/gsemet/okf-schema) bundle. Each `.md`
9
+ file has a `type` in its frontmatter that maps to a schema in `_schema/`. This
10
+ document is the strict minimal rule set for maintaining it correctly.
11
+
12
+ ## 1. Choose the right type
13
+
14
+ | You want to record… | type | Folder | Nature |
15
+ |---------------------|------|--------|--------|
16
+ | A stable idea / "what is this?" | `Concept` | `concepts/` | Explanatory |
17
+ | How an object is composed / works | `Structure` | `structures/` | Descriptive |
18
+ | A standard or convention (agreed with humans) | `Principle` | `principles/` | Normative |
19
+ | A step-by-step procedure to perform | `Playbook` | `guides/` | Procedural |
20
+ | Exact values, fields, or lookup tables | `Reference` | `reference/` | Lookup |
21
+ | What you observed/believed at time T | `Finding` | `findings/` | Empirical, dated |
22
+ | A reusable procedure to test a claim | `Experiment` | `experiments/` | Template, run 1–2× |
23
+
24
+ Rules of thumb:
25
+
26
+ - Document only what is **non-trivial** for coding agents. Do not paraphrase code
27
+ or existing docs — link instead.
28
+ - Keep each file focused and concise, important information first.
29
+ - Findings and Experiments are the empirical layer; the other five are the stable
30
+ layer. Agents dump Findings freely; stable docs are promoted deliberately by the
31
+ `consolidate-knowledge-base` skill — never dumped ad hoc.
32
+
33
+ ## 2. Required frontmatter
34
+
35
+ All documents (except `index.md` and `log.md`) require:
36
+
37
+ ```yaml
38
+ type: <one of the types above> # must match the const in _schema/<Type>.schema.yaml
39
+ title: Human-Readable Title # non-empty
40
+ description: Short summary. # non-empty
41
+ tags: [keyword] # optional but encouraged
42
+ timestamp: 2026-07-02T00:00:00Z # ISO 8601 (YYYY-MM-DDTHH:MM:SSZ)
43
+ ```
44
+
45
+ Type-specific required fields:
46
+
47
+ - **Finding**: also `timestamp`, `confidence` (`low|medium|high`), and `context`
48
+ (what you believed and the scope you actually tested).
49
+ - **Experiment**: also `hypothesis` and `steps`.
50
+
51
+ ## 3. Finding immutability & contradictions
52
+
53
+ - A Finding's **body and claim are frozen** once written. Never reword or delete.
54
+ - To correct a Finding, write a NEW Finding with `contradicts: [<old-id>]` or
55
+ `supersedes: [<old-id>]`.
56
+ - The only permitted edits to an existing Finding are the lifecycle fields
57
+ `status` (`contradicted|superseded`), `contradicted_by`, `superseded_by`,
58
+ appended by the `consolidate-knowledge-base` review.
59
+ - Promotion of converged Findings into Concept/Structure/Principle is done by
60
+ `consolidate-knowledge-base` with human confirmation — Principles are always
61
+ agreed with humans.
62
+
63
+ ## 4. Skills
64
+
65
+ - **`record-finding`** (fast, non-interactive): dump one Finding after an
66
+ investigation or debugging session.
67
+ - **`consolidate-knowledge-base`** (interactive, human-confirmed): detect
68
+ contradictions, mark findings, propose Experiments, propose promotions.
69
+
70
+ ## 5. Validate before commit
71
+
72
+ ```bash
73
+ just knowledge-lint # auto-format frontmatter + rebuild index
74
+ just knowledge-validate # 0 errors, 0 warnings required
75
+ just knowledge-lint-check # verify no pending format changes
76
+ ```
77
+
78
+ Pre-commit checklist:
79
+
80
+ - [ ] Correct `type` and folder for the information recorded.
81
+ - [ ] Required frontmatter present and valid.
82
+ - [ ] No Finding body was reworded or deleted.
83
+ - [ ] All three commands above pass (also covered by `just preflight`).
84
+
85
+ Add a dated entry to `knowledge/log.md` for significant changes. Use plain
86
+ ISO-8601 date headings; avoid parenthetical annotations (they trigger warnings).
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: consolidate-knowledge-base
3
+ description: 'Interactively review the OKF knowledge base to detect contradictions between Findings, mark contradicted/superseded Findings, propose Experiments to resolve open questions, and propose promotions of converged Findings into stable Concept/Structure/Principle documents. Every mutation is confirmed by a human before it is written. Use periodically or after a batch of recorded Findings.'
4
+ ---
5
+
6
+ # consolidate-knowledge-base
7
+
8
+ Turn a pile of dated Findings into consolidated, trustworthy knowledge — without
9
+ ever rewriting history. This skill is **interactive**: it proposes, the human
10
+ confirms, then it writes.
11
+
12
+ ## When to use
13
+
14
+ - After a batch of Findings has been dumped by `record-finding`.
15
+ - Periodically, to keep the empirical layer coherent with the stable layer.
16
+ - When you suspect two findings disagree.
17
+
18
+ ## Guardrails
19
+
20
+ - NEVER edit or delete a Finding's body. Only append lifecycle frontmatter
21
+ (`status`, `contradicted_by`, `superseded_by`).
22
+ - NEVER promote to a Principle without explicit human confirmation — principles
23
+ are agreed with humans.
24
+ - Ask before every write, using `vscode_askQuestions`.
25
+
26
+ ## Procedure
27
+
28
+ ### 1. Scan
29
+ Read `knowledge/findings/`, plus `principles/`, `structures/`, `concepts/`.
30
+ Build a map of claims, tags, and existing `contradicts`/`supersedes` links.
31
+
32
+ ### 2. Detect contradictions
33
+ Identify pairs where a newer Finding disagrees with an older Finding, or where a
34
+ Finding conflicts with a Principle/Structure/Concept. Present each candidate
35
+ contradiction to the human for confirmation.
36
+
37
+ ### 3. Mark (on confirmation)
38
+ For each confirmed contradiction, append metadata-only fields:
39
+ - On the newer finding: `contradicts: [<old-id>]` (if not already present).
40
+ - On the older finding: `status: contradicted` and `contradicted_by: [<new-id>]`.
41
+ Use the same pattern with `supersedes`/`superseded_by` for replacements.
42
+ The body of both files stays untouched.
43
+
44
+ ### 4. Propose Experiments
45
+ For unresolved or low-confidence contradictions, propose a new `Experiment`
46
+ document (hypothesis, steps, expected_signals, `max_runs: 1–2`) that would
47
+ settle the question. Write it to `knowledge/experiments/` only on confirmation.
48
+
49
+ ### 5. Propose promotions
50
+ When several Findings converge on a stable truth, propose promoting the insight
51
+ into the stable layer:
52
+ - "how it works" → `Structure` in `structures/`
53
+ - "the idea" → `Concept` in `concepts/`
54
+ - "the standard/convention" → `Principle` in `principles/` (always human-agreed)
55
+ Link the promoted doc back to its supporting findings (`supported_by` /
56
+ `related_concepts`). Write only on confirmation. Findings remain untouched.
57
+
58
+ ### 6. Validate
59
+ ```bash
60
+ just knowledge-lint
61
+ just knowledge-validate
62
+ ```
63
+ Both must pass before finishing.
64
+
65
+ ## Output
66
+
67
+ A short chat summary: contradictions found and marked, experiments proposed,
68
+ promotions made, and any open questions left for a future run.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: record-finding
3
+ description: 'Dump a single empirical Finding into the OKF knowledge base after an investigation or debugging session. Fast and non-interactive. Records what you truthfully observed and believed at this moment, with confidence and context, as an immutable dated note under knowledge/findings/. Use after diagnosing a bug, verifying behavior, or discovering something non-trivial worth remembering.'
4
+ ---
5
+
6
+ # record-finding
7
+
8
+ Record ONE Finding: a dated, empirical, falsifiable note of what you observed and
9
+ believed right now. Findings can later be wrong — that is fine. Be truthful about
10
+ the moment, not about eternal truth.
11
+
12
+ ## When to use
13
+
14
+ - You just finished an investigation, debugging session, or verification.
15
+ - You learned something non-trivial about how the external world (VS Code,
16
+ Copilot, pricing, logs) behaves.
17
+ - You want to hand off "what I found and believed" for later consolidation.
18
+
19
+ Do NOT use this to record standards/conventions (that is a Principle), how an
20
+ object is composed (Structure), or a stable idea (Concept). Those are promoted
21
+ deliberately by `consolidate-knowledge-base`, not dumped.
22
+
23
+ ## Procedure
24
+
25
+ 1. Write exactly one file to `knowledge/findings/<slug>.md` where `<slug>` is a
26
+ short hyphenated summary of the claim.
27
+ 2. Use this frontmatter (all listed fields are required):
28
+
29
+ ```yaml
30
+ ---
31
+ type: Finding
32
+ title: Short claim as a title
33
+ description: One-sentence summary of the finding.
34
+ tags: [relevant, keywords]
35
+ timestamp: <ISO-8601 UTC, e.g. 2026-07-02T14:30:00Z>
36
+ confidence: low | medium | high
37
+ context: >-
38
+ What you believed and the situation at the time — including assumptions
39
+ that may later prove wrong, and the scope you actually tested.
40
+ ---
41
+ ```
42
+
43
+ 3. In the body, state plainly: what was observed, why it matters, and the
44
+ caveats / limits of what you verified.
45
+ 4. If this finding contradicts or replaces an earlier one, add
46
+ `contradicts: [<finding-id>]` or `supersedes: [<finding-id>]`. Do NOT edit the
47
+ older finding — the `consolidate-knowledge-base` skill handles backlinks.
48
+ 5. If a run of an Experiment produced this finding, add `derived_from: <experiment-id>`.
49
+
50
+ ## Immutability
51
+
52
+ Once written, never reword or delete a finding's body. This is enforced by the
53
+ `Findings Are Immutable` principle. Corrections happen by writing a NEW finding.
54
+
55
+ ## Validate
56
+
57
+ ```bash
58
+ just knowledge-lint
59
+ just knowledge-validate
60
+ ```
61
+
62
+ Both must pass. Do not run `consolidate-knowledge-base` here — dumping stays fast.
@@ -43,6 +43,7 @@ jobs:
43
43
  with:
44
44
  files: ./coverage.xml
45
45
  fail_ci_if_error: false
46
+ token: ${{ secrets.CODECOV_TOKEN }}
46
47
 
47
48
  cross-platform:
48
49
  runs-on: ${{ matrix.os }}
@@ -0,0 +1,24 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ version: 2
5
+
6
+ build:
7
+ os: ubuntu-24.04
8
+ tools:
9
+ python: "3.13"
10
+ jobs:
11
+ post_checkout:
12
+ - git fetch --tags
13
+ pre_build:
14
+ - uv run cz changelog
15
+
16
+ sphinx:
17
+ configuration: docs/source/conf.py
18
+
19
+ python:
20
+ install:
21
+ - method: uv
22
+ command: sync
23
+ groups:
24
+ - dev
@@ -0,0 +1,13 @@
1
+ ## Unreleased
2
+
3
+ ## v0.2.0 (2026-07-02)
4
+
5
+ ### Fix
6
+
7
+ - bad cost compuation for Opus 4.8
8
+
9
+ ## v0.1.0 (2026-07-02)
10
+
11
+ ### Feat
12
+
13
+ - initial implementation
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copilot-session-usage
3
- Version: 0.1.0
3
+ Version: 0.2.1
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
- Project-URL: Documentation, https://copilot-session-usage.readthedocs.io
6
+ Project-URL: Documentation, https://copilot-session-usage.readthedocs.io/en/stable/
7
7
  Project-URL: Repository, https://github.com/gsemet/copilot-session-usage
8
8
  Project-URL: Issues, https://github.com/gsemet/copilot-session-usage/issues
9
9
  Author-email: Gaetan Semet <gaetan@xeberon.net>
@@ -20,6 +20,7 @@ Description-Content-Type: text/markdown
20
20
  [![Coverage](https://img.shields.io/codecov/c/github/gsemet/copilot-session-usage)](https://codecov.io/gh/gsemet/copilot-session-usage)
21
21
  [![PyPI](https://img.shields.io/pypi/v/copilot-session-usage)](https://pypi.org/project/copilot-session-usage/)
22
22
  [![Python Versions](https://img.shields.io/pypi/pyversions/copilot-session-usage)](https://pypi.org/project/copilot-session-usage/)
23
+ [![Docs](https://readthedocs.org/projects/copilot-session-usage/badge/?version=stable)](https://copilot-session-usage.readthedocs.io/en/stable/)
23
24
  [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
24
25
  [![Type checked](https://img.shields.io/badge/type%20checked-mypy%2Fty-blue.svg)](./)
25
26
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -182,6 +183,8 @@ just docs
182
183
  just docs-serve
183
184
  ```
184
185
 
186
+ **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/)
187
+
185
188
  ## License
186
189
 
187
190
  MIT — see [LICENSE](LICENSE).
@@ -4,6 +4,7 @@
4
4
  [![Coverage](https://img.shields.io/codecov/c/github/gsemet/copilot-session-usage)](https://codecov.io/gh/gsemet/copilot-session-usage)
5
5
  [![PyPI](https://img.shields.io/pypi/v/copilot-session-usage)](https://pypi.org/project/copilot-session-usage/)
6
6
  [![Python Versions](https://img.shields.io/pypi/pyversions/copilot-session-usage)](https://pypi.org/project/copilot-session-usage/)
7
+ [![Docs](https://readthedocs.org/projects/copilot-session-usage/badge/?version=stable)](https://copilot-session-usage.readthedocs.io/en/stable/)
7
8
  [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
8
9
  [![Type checked](https://img.shields.io/badge/type%20checked-mypy%2Fty-blue.svg)](./)
9
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -166,6 +167,8 @@ just docs
166
167
  just docs-serve
167
168
  ```
168
169
 
170
+ **Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/)
171
+
169
172
  ## License
170
173
 
171
174
  MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,25 @@
1
+ /* Rewrite changelog category headings */
2
+ document.addEventListener('DOMContentLoaded', function () {
3
+ const map = {
4
+ 'Feat': '✨ Features',
5
+ 'Fix': '🔧 Bug Fixes',
6
+ 'Docs': '📚 Documentation',
7
+ 'Chore': '🧹 Chores',
8
+ 'Refactor': '🛠 Refactors',
9
+ 'Test': '🧪 Tests',
10
+ 'CI': '🤖 CI',
11
+ 'Perf': '⚡ Performance',
12
+ 'Build': '🏗 Build',
13
+ 'Style': '🎨 Styles',
14
+ };
15
+
16
+ document.querySelectorAll('h3').forEach(function (h3) {
17
+ const text = h3.childNodes[0];
18
+ if (text && text.nodeType === Node.TEXT_NODE) {
19
+ const trimmed = text.textContent.trim();
20
+ if (map[trimmed]) {
21
+ text.textContent = ' ' + map[trimmed] + ' ';
22
+ }
23
+ }
24
+ });
25
+ });
@@ -0,0 +1,142 @@
1
+ /* Custom styles for copilot-session-usage documentation */
2
+
3
+ /* ── Changelog ── */
4
+ #changelog h2 {
5
+ font-size: 1.4em;
6
+ font-weight: 600;
7
+ margin-top: 2.5em;
8
+ padding-bottom: 0.4em;
9
+ border-bottom: 1px solid var(--color-background-border);
10
+ }
11
+
12
+ #changelog h2:first-of-type {
13
+ margin-top: 0.5em;
14
+ }
15
+
16
+ #changelog h2#unreleased {
17
+ color: var(--color-brand-primary);
18
+ }
19
+
20
+ #changelog h3 {
21
+ font-size: 0.8em;
22
+ font-weight: 600;
23
+ text-transform: uppercase;
24
+ letter-spacing: 0.08em;
25
+ margin: 1.5em 0 0.6em;
26
+ padding: 0.3rem 0.6rem;
27
+ display: inline-block;
28
+ }
29
+
30
+ /* Features */
31
+ #changelog section[id="feat"] > h3,
32
+ #changelog section[id="id1"] > h3,
33
+ #changelog section[id="id4"] > h3,
34
+ #changelog section[id="id6"] > h3,
35
+ #changelog section[id="id8"] > h3,
36
+ #changelog section[id="id10"] > h3 {
37
+ font-size: 0;
38
+ color: transparent;
39
+ background: rgba(26, 127, 55, 0.08);
40
+ }
41
+
42
+ #changelog section[id="feat"] > h3::before,
43
+ #changelog section[id="id1"] > h3::before,
44
+ #changelog section[id="id4"] > h3::before,
45
+ #changelog section[id="id6"] > h3::before,
46
+ #changelog section[id="id8"] > h3::before,
47
+ #changelog section[id="id10"] > h3::before {
48
+ content: "✨ Features";
49
+ font-size: 0.8rem;
50
+ color: #1a7f37;
51
+ }
52
+
53
+ /* Bug Fixes */
54
+ #changelog section[id="fix"] > h3,
55
+ #changelog section[id="id2"] > h3,
56
+ #changelog section[id="id3"] > h3,
57
+ #changelog section[id="id5"] > h3,
58
+ #changelog section[id="id7"] > h3,
59
+ #changelog section[id="id9"] > h3 {
60
+ font-size: 0;
61
+ color: transparent;
62
+ background: rgba(154, 103, 0, 0.08);
63
+ }
64
+
65
+ #changelog section[id="fix"] > h3::before,
66
+ #changelog section[id="id2"] > h3::before,
67
+ #changelog section[id="id3"] > h3::before,
68
+ #changelog section[id="id5"] > h3::before,
69
+ #changelog section[id="id7"] > h3::before,
70
+ #changelog section[id="id9"] > h3::before {
71
+ content: "🔧 Bug Fixes";
72
+ font-size: 0.8rem;
73
+ color: #9a6700;
74
+ }
75
+
76
+ #changelog ul {
77
+ margin-top: 0.5em;
78
+ padding-left: 1.2em;
79
+ }
80
+
81
+ #changelog li {
82
+ margin-bottom: 0.35em;
83
+ line-height: 1.6;
84
+ }
85
+
86
+ /* ── Landing page cards ── */
87
+ .sd-card {
88
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
89
+ }
90
+
91
+ .sd-card:hover {
92
+ transform: translateY(-2px);
93
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
94
+ }
95
+
96
+ /* ── Copy button ── */
97
+ button.copybtn {
98
+ opacity: 0.6;
99
+ transition: opacity 0.2s;
100
+ }
101
+
102
+ button.copybtn:hover {
103
+ opacity: 1;
104
+ }
105
+
106
+ /* ── CLI tables ── */
107
+ table.docutils {
108
+ font-size: 0.95em;
109
+ }
110
+
111
+ table.docutils th {
112
+ background: var(--color-background-secondary);
113
+ }
114
+
115
+ /* ── API signatures ── */
116
+ dl.py.function,
117
+ dl.py.class,
118
+ dl.py.method {
119
+ margin: 1.5em 0;
120
+ }
121
+
122
+ dl.py.function > dd,
123
+ dl.py.class > dd,
124
+ dl.py.method > dd {
125
+ margin-left: 0;
126
+ padding-left: 1em;
127
+ }
128
+
129
+ dt.sig.sig-object.py {
130
+ background: var(--color-background-secondary);
131
+ border-left: 3px solid var(--color-brand-primary);
132
+ border-radius: 0;
133
+ margin-left: 0;
134
+ margin-right: 0;
135
+ padding: 0.6em 0.8em;
136
+ line-height: 1.6;
137
+ text-indent: 0;
138
+ }
139
+
140
+ dl.py.class > dt.sig.sig-object.py {
141
+ border-left-color: var(--color-brand-content);
142
+ }
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ```{include} ../../CHANGELOG.md
4
+ ```
@@ -17,6 +17,8 @@ extensions = [
17
17
  "sphinx.ext.napoleon",
18
18
  "sphinx_click",
19
19
  "sphinx_autodoc_typehints",
20
+ "sphinx_design",
21
+ "sphinx_copybutton",
20
22
  ]
21
23
 
22
24
  myst_enable_extensions = ["colon_fence", "deflist"]
@@ -24,6 +26,8 @@ myst_enable_extensions = ["colon_fence", "deflist"]
24
26
  html_theme = "furo"
25
27
  html_title = f"copilot-session-usage {version}"
26
28
  html_static_path = ["_static"]
29
+ html_css_files = ["custom.css"]
30
+ html_js_files = ["changelog.js"]
27
31
 
28
32
  autodoc_member_order = "bysource"
29
33
  autodoc_typehints = "description"
@@ -0,0 +1,96 @@
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
+ For each model, cost is computed as:
66
+
67
+ ```
68
+ cost = (input_tokens - cached_tokens) / 1_000_000 × input_price
69
+ + cached_tokens / 1_000_000 × cached_input_price
70
+ + output_tokens / 1_000_000 × output_price
71
+ ```
72
+
73
+ Prices come from the bundled `models-and-pricing.yml`. For models with
74
+ long-context tier switching (e.g., GPT-5.4 above 272K tokens), the tool
75
+ selects the correct price row automatically.
76
+
77
+ ---
78
+
79
+ ## Subagent attribution
80
+
81
+ `runSubagent` calls appear in the JSONL as a distinct event type. The tool
82
+ tracks them separately so `--detail full` can show which fraction of tokens
83
+ was consumed by subagents vs. the main conversation.
84
+
85
+ ---
86
+
87
+ ## Accuracy
88
+
89
+ Prices match the published GitHub Copilot per-token rates for each model.
90
+ The tool applies the same formula GitHub uses: input tokens (minus cached)
91
+ at the full input rate, cached tokens at the cache-hit rate, output tokens
92
+ at the output rate. Long-context tier switching is automatic.
93
+
94
+ The main source of variance is pricing lag: the bundled table is updated
95
+ manually with each release. Run `just refresh-pricing` to pull the latest
96
+ rates.
@@ -0,0 +1,9 @@
1
+ # How It Works
2
+
3
+ Background and design notes.
4
+
5
+ ```{toctree}
6
+ :maxdepth: 1
7
+
8
+ how-cost-estimation-works
9
+ ```
@@ -0,0 +1,46 @@
1
+ # Analyze a Specific Session
2
+
3
+ Use this when you know the path to a session's debug-log directory or its UUID,
4
+ and `latest` would pick the wrong session.
5
+
6
+ ## By debug-log path
7
+
8
+ Each session is a directory inside VS Code's `workspaceStorage`:
9
+
10
+ ```bash
11
+ copilot-session-usage analyze \
12
+ "/path/to/workspaceStorage/<hash>/GitHub.copilot-chat/debug-logs/<session-uuid>"
13
+ ```
14
+
15
+ The path always ends in a UUID directory. Use `list` to find the right one if
16
+ you're unsure.
17
+
18
+ ## By UUID
19
+
20
+ If you have a session ID from a previous `list` or `find` run:
21
+
22
+ ```bash
23
+ copilot-session-usage id 3a91c012-1b4e-4c8a-9f72-ab12cd34ef56
24
+ ```
25
+
26
+ The tool searches all workspaceStorage roots automatically.
27
+
28
+ ## By title substring
29
+
30
+ ```bash
31
+ copilot-session-usage find "CI pipeline"
32
+ ```
33
+
34
+ Matching is case-insensitive substring search. If multiple sessions match,
35
+ the tool lists them and exits without analyzing — then use `id` to pick one.
36
+
37
+ ## Locating workspaceStorage manually
38
+
39
+ | Platform | Default path |
40
+ |----------|-------------|
41
+ | macOS | `~/Library/Application Support/Code/User/workspaceStorage/` |
42
+ | Linux | `~/.config/Code/User/workspaceStorage/` |
43
+ | Windows | `%APPDATA%\Code\User\workspaceStorage\` |
44
+
45
+ Each subdirectory under `workspaceStorage/` corresponds to one VS Code workspace.
46
+ Inside it, `GitHub.copilot-chat/debug-logs/` contains one directory per session.