UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

53 lines (52 loc) • 3.28 kB
/** * Reads token usage out of Copilot CLI's local SQLite store. * * Store: `~/.copilot/session-store.db`. Usage lives on the * `assistant_usage_events` table — one INSERT-only row per assistant turn, * with `model`, `input_tokens`, `output_tokens`, `cache_read_tokens`, * `cache_write_tokens`, `reasoning_tokens` and a `created_at` timestamp * (ISO-8601 with a `Z` suffix). Confirmed no duplicate `(session_id, * turn_index)` pair exists on a reference machine, so — like OpenCode's * `message` table — this needs no dedup logic beyond the table's own * uniqueness: every row is counted once, matching the `rowid-high-water-mark` * strategy already established for that reader. * * The same database also holds a JSONL-adjacent `session.shutdown` event with * its own `modelMetrics`/`tokenDetails` payload (written to * `~/.copilot/session-state/*\/events.jsonl`, not this database). It was * deliberately NOT used here: cross-checking real sessions confirmed the two * sources report identical totals for the sessions they both cover, so * combining them would double-count rather than add coverage. The SQLite * table is the sole source; the tradeoff is a disclosed gap for any history * that predates the table's introduction. * * `cache_read_tokens` and `cache_write_tokens` are both SUBSETS of * `input_tokens`, not disjoint — confirmed arithmetically against a real * `session.shutdown` record (session `c2c38d0b`): `tokenDetails.input.tokenCount * = 3`, `cache_write = 24047`, and `usage.inputTokens = 24050` — exactly * `3 + 24047`, with nothing left over for a separate additive interpretation. * So `inputTokens` here is `input_tokens - cache_read_tokens - * cache_write_tokens`, the same style of subtraction `codexReader.ts`, * `qwenCodeReader.ts` and `geminiCliReader.ts` make for the same reason: this * subsystem's `LocalUsageTotals.inputTokens` + `.cacheReadTokens` must sum to * the true prompt size without double-counting. `reasoning_tokens` folds into * output — Copilot's own SDK types (`ShutdownModelMetricUsage`) group it * alongside `outputTokens` as a further breakdown of output, not a separate * accounting bucket. * * Cost is deliberately `unavailable`. The table's own `request_multiplier` * and `total_nano_aiu` columns are Copilot's request-quota accounting, not a * USD figure — the SDK's own generated types tag the closest concept, * `ShutdownModelMetricUsage.cost`, `@experimental`, and every real sample row * on the reference machine had `request_multiplier: 0.0`. Modeling a * per-token dollar figure from public list prices would also ignore that * Copilot CLI is typically used under a flat-rate Copilot subscription, the * same reasoning that keeps Codex's confidence `unavailable`. This holds even * when the underlying model is a metered vendor's (e.g. `claude-haiku-4-5` on * the reference machine) — Copilot's telemetry layer normalizes across * backend vendors into its own accounting convention, and this reader has no * way to tell whether a given row was billed by the minute, by the token, or * not separately billed at all. */ import type { LocalUsageReader } from "../types/index.js"; export declare function createCopilotCliReader(): Promise<LocalUsageReader>;