Skip to content

feat(source): add Cursor cache adapter #58

@ayagmar

Description

@ayagmar

Objective

Add a cursor source adapter for local usage CSV caches so Cursor usage can be parsed without introducing auth or sync behavior into this repository.

Source shape to support

  • directory-backed cache source containing usage.csv and usage.<account>.csv
  • at least two known CSV header layouts must be supported
  • rows carry explicit cost
  • timestamps may be full ISO datetimes or date-only values
  • model strings may need conservative provider inference

Implementation plan

  1. Adapter file

    • add src/sources/cursor/cursor-source-adapter.ts
    • implement SourceAdapter with id = 'cursor'
    • keep this source parse-only; do not add login, API sync, or cache-population behavior here
  2. Discovery

    • treat this as a directory-backed source reachable through generic --source-dir cursor=...
    • discover the cache files deterministically and ignore unrelated files
    • account-scoped files should remain distinct inputs rather than being merged before parsing
  3. Parsing

    • support both known CSV header layouts instead of assuming one fixed column order
    • preserve explicit cost through createUsageEvent({ costUsd, costMode: 'explicit' })
    • infer provider conservatively from the model string; do not overclaim fixed-provider capabilities for this source
    • keep cache write tokens derived from the delta between “input with cache write” and “input without cache write” when the file shape exposes both
    • for date-only rows, assign a stable in-day timestamp (rather than a boundary timestamp that can drift across local-day bucketing)
    • skip blank / malformed rows without aborting the whole file
    • if diagnostics are worthwhile, implement parseFileWithDiagnostics() so malformed-row counts are visible
  4. Wiring

    • register cursor in src/sources/create-default-adapters.ts
    • make sure supported-source IDs and help output reflect the new source
    • do not add a bespoke --cursor-dir flag unless implementation proves generic --source-dir is insufficient
  5. Tests and docs

    • add tests/sources/cursor-source-adapter.test.ts
    • update shared registry/help tests that assert supported source IDs/counts
    • document the supported cache file shapes and --source-dir cursor=... usage in README.md

Code paths to touch

  • src/sources/cursor/cursor-source-adapter.ts
  • src/sources/create-default-adapters.ts
  • src/sources/parsing-utils.ts
  • src/domain/usage-event.ts
  • tests/sources/cursor-source-adapter.test.ts
  • tests/sources/create-default-adapters.test.ts
  • tests/cli/create-cli.test.ts
  • README.md

Verification

  • parser fixtures cover:
    • both CSV header layouts
    • usage.csv and usage.<account>.csv
    • blank/malformed rows skipped cleanly
    • date-only timestamp handling is stable for report bucketing
    • explicit cost is preserved
    • provider inference stays conservative
  • llm-usage daily --source cursor --source-dir cursor=<fixture-dir> works
  • no auth/sync commands, credentials, or network code are introduced
  • full validation passes:
    • pnpm run lint
    • pnpm run typecheck
    • pnpm run test
    • pnpm run format:check

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions