diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7cae1..54ca33f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.1] - 2026-07-16 + +### Fixed + +- Corrected fresh-input accounting so both cache reads and cache writes are excluded from fresh tokens, including alternate OpenTelemetry cache attribute names emitted by Copilot CLI. +- Corrected the dashboard pricing table to use the bundled `cached_input` field and expanded per-call details to show fresh input, cache reads, and cache writes separately. + ## [0.3.0] - 2026-05-21 ### Changed diff --git a/package-lock.json b/package-lock.json index c4e1fd6..0581d80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "copilot-cost", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "copilot-cost", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "dependencies": { "chart.js": "^4.4.4", diff --git a/package.json b/package.json index 3d16a42..03f6c4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "copilot-cost", - "version": "0.3.0", + "version": "0.3.1", "description": "Local-only GitHub Copilot CLI statusline + dashboard for real-time token cost tracking. Reads OpenTelemetry traces, never sends data anywhere.", "keywords": [ "github", diff --git a/tests-ts/otel-aggregations.test.ts b/tests-ts/otel-aggregations.test.ts index 118cd77..da0eb85 100644 --- a/tests-ts/otel-aggregations.test.ts +++ b/tests-ts/otel-aggregations.test.ts @@ -1,9 +1,10 @@ +import { randomUUID } from "node:crypto"; import { describe, expect, it } from "vitest"; import { exportCsv, models, sessions, sessionDetail, summary, timeseries } from "../src/otel/aggregations.js"; import { type NormalizedCall } from "../src/otel/parser.js"; function call(partial: Partial): NormalizedCall { - return { dedup_key: partial.dedup_key ?? crypto.randomUUID(), session_id: Object.hasOwn(partial, "session_id") ? partial.session_id! : "s1", ts: partial.ts ?? "2026-05-13T12:00:00.000Z", model: partial.model ?? "m1", input_tokens: partial.input_tokens ?? 0, output_tokens: partial.output_tokens ?? 0, cache_read: partial.cache_read ?? 0, cache_creation: partial.cache_creation ?? 0, reasoning: partial.reasoning ?? 0, usd_cost: partial.usd_cost ?? 0, duration_ms: partial.duration_ms ?? 0, source: partial.source ?? "cli-span" }; + return { dedup_key: partial.dedup_key ?? randomUUID(), session_id: Object.hasOwn(partial, "session_id") ? partial.session_id! : "s1", ts: partial.ts ?? "2026-05-13T12:00:00.000Z", model: partial.model ?? "m1", input_tokens: partial.input_tokens ?? 0, output_tokens: partial.output_tokens ?? 0, cache_read: partial.cache_read ?? 0, cache_creation: partial.cache_creation ?? 0, reasoning: partial.reasoning ?? 0, usd_cost: partial.usd_cost ?? 0, duration_ms: partial.duration_ms ?? 0, source: partial.source ?? "cli-span" }; } describe("OTel aggregations", () => {