agent-usage-report 0.1.0
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.
- package/AGENTS.md +78 -0
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -0
- package/dist/generator.d.ts +112 -0
- package/dist/generator.js +1417 -0
- package/dist/generator.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +7 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/generator.d.ts +112 -0
- package/dist/src/generator.js +1417 -0
- package/dist/src/generator.js.map +1 -0
- package/dist/src/template.html +1837 -0
- package/dist/template.html +1837 -0
- package/package.json +42 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# AGENTS.md - agent-usage-report
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
- This is a standalone TypeScript CLI package intended for `pnpm`, `bun`, `node`, and eventual `npx` usage.
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
- Generate a self-contained local agent usage HTML report and JSON payload
|
|
8
|
+
- Maintain feature parity with the Python implementation in the sibling local project
|
|
9
|
+
- Support current local providers:
|
|
10
|
+
- Codex
|
|
11
|
+
- Claude Code
|
|
12
|
+
- OpenCode
|
|
13
|
+
- Pi Coding Agent
|
|
14
|
+
- Preserve provider-aware reporting:
|
|
15
|
+
- per-provider views
|
|
16
|
+
- combined view
|
|
17
|
+
- daily totals
|
|
18
|
+
- monthly rollups
|
|
19
|
+
- Codex and Claude monthly spend-vs-plan comparison
|
|
20
|
+
- Claude `history.jsonl` activity-only fallback days
|
|
21
|
+
|
|
22
|
+
## Primary Entry Points
|
|
23
|
+
- CLI entry: `src/cli.ts`
|
|
24
|
+
- Core logic: `src/generator.ts`
|
|
25
|
+
- HTML template: `src/template.html`
|
|
26
|
+
- Tests: `test/generator.test.ts`
|
|
27
|
+
|
|
28
|
+
## Build And Test
|
|
29
|
+
- Install: `pnpm install`
|
|
30
|
+
- Typecheck: `pnpm run typecheck`
|
|
31
|
+
- Test: `pnpm run test`
|
|
32
|
+
- Build: `pnpm run build`
|
|
33
|
+
- Smoke run:
|
|
34
|
+
- `node dist/cli.js --help`
|
|
35
|
+
- `bun run src/cli.ts --help`
|
|
36
|
+
|
|
37
|
+
## Packaging Expectations
|
|
38
|
+
- Package name: `agent-usage-report`
|
|
39
|
+
- Intended runner UX:
|
|
40
|
+
- `npx agent-usage-report@latest`
|
|
41
|
+
- `bunx agent-usage-report@latest`
|
|
42
|
+
- Do not introduce native dependencies unless strictly required for distribution.
|
|
43
|
+
- Prefer Node built-ins over native modules when possible so package-runner adoption stays easy.
|
|
44
|
+
|
|
45
|
+
## Current CLI Surface
|
|
46
|
+
- `--codex-home`
|
|
47
|
+
- `--claude-config-dir`
|
|
48
|
+
- `--opencode-dir`
|
|
49
|
+
- `--pi-agent-dir`
|
|
50
|
+
- `--timezone`
|
|
51
|
+
- `--output-html`
|
|
52
|
+
- `--output-json`
|
|
53
|
+
- `--skip-archived`
|
|
54
|
+
|
|
55
|
+
## Implementation Notes
|
|
56
|
+
- Keep the JSON payload shape aligned with the Python project:
|
|
57
|
+
- `schemaVersion`
|
|
58
|
+
- `providerOrder`
|
|
59
|
+
- `providers`
|
|
60
|
+
- `combined`
|
|
61
|
+
- top-level default-provider mirrors
|
|
62
|
+
- Claude `history.jsonl` days are activity-only:
|
|
63
|
+
- they should render in the heatmap
|
|
64
|
+
- they must not contribute to token totals or spend
|
|
65
|
+
- OpenCode should prefer `opencode.db` when available and fall back to `storage/message/**/*.json`
|
|
66
|
+
|
|
67
|
+
## Editing Guidance
|
|
68
|
+
- Prefer targeted edits in `src/generator.ts` until the port stabilizes
|
|
69
|
+
- If changing the UI, edit `src/template.html` or the template-loading flow carefully
|
|
70
|
+
- After behavior changes:
|
|
71
|
+
- rerun `pnpm run typecheck`
|
|
72
|
+
- rerun `pnpm run test`
|
|
73
|
+
- rerun `pnpm run build`
|
|
74
|
+
|
|
75
|
+
## Non-Goals
|
|
76
|
+
- Do not turn this into a monorepo unless clearly needed
|
|
77
|
+
- Do not add a backend here
|
|
78
|
+
- Do not reduce current provider/report parity with the Python version
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ignacio Alonso
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# agent-usage-report
|
|
2
|
+
|
|
3
|
+
`agent-usage-report` scans local agent usage data on your machine and generates a self-contained HTML report you can open directly in the browser.
|
|
4
|
+
|
|
5
|
+
Current providers:
|
|
6
|
+
- Codex
|
|
7
|
+
- Claude Code
|
|
8
|
+
- OpenCode
|
|
9
|
+
- Pi Coding Agent
|
|
10
|
+
|
|
11
|
+
Features:
|
|
12
|
+
- GitHub-style daily heatmap
|
|
13
|
+
- Per-provider and combined views
|
|
14
|
+
- Estimated token-cost reporting
|
|
15
|
+
- Daily cost tables
|
|
16
|
+
- Monthly spend-vs-plan comparison for Codex and Claude
|
|
17
|
+
- Claude legacy activity fallback from `history.jsonl`
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
Run without installing globally:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx agent-usage-report@latest
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
With Bun:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bunx agent-usage-report@latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Local development:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm install
|
|
37
|
+
pnpm run build
|
|
38
|
+
node dist/cli.js
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
agent-usage-report \
|
|
45
|
+
--codex-home ~/.codex \
|
|
46
|
+
--claude-config-dir ~/.config/claude,~/.claude \
|
|
47
|
+
--opencode-dir ~/.local/share/opencode \
|
|
48
|
+
--pi-agent-dir ~/.pi/agent \
|
|
49
|
+
--timezone America/Mexico_City \
|
|
50
|
+
--output-html agent-usage-report.html \
|
|
51
|
+
--output-json agent-usage-data.json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Flags:
|
|
55
|
+
- `--codex-home`: Codex home directory
|
|
56
|
+
- `--claude-config-dir`: Claude config directory or comma-separated directories
|
|
57
|
+
- `--opencode-dir`: OpenCode data directory
|
|
58
|
+
- `--pi-agent-dir`: Pi Coding Agent directory or sessions directory
|
|
59
|
+
- `--timezone`: IANA timezone for day bucketing
|
|
60
|
+
- `--output-html`: HTML output path
|
|
61
|
+
- `--output-json`: JSON output path
|
|
62
|
+
- `--skip-archived`: skip `~/.codex/archived_sessions`
|
|
63
|
+
|
|
64
|
+
## Privacy
|
|
65
|
+
|
|
66
|
+
The CLI reads local usage data and generates local files.
|
|
67
|
+
|
|
68
|
+
The generated HTML and JSON reports stay on your machine unless you choose to share them manually.
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm install
|
|
74
|
+
pnpm run typecheck
|
|
75
|
+
pnpm run test
|
|
76
|
+
pnpm run build
|
|
77
|
+
```
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
declare const FREE_MODEL_PRICING: {
|
|
2
|
+
inputCostPerMToken: number;
|
|
3
|
+
cachedInputCostPerMToken: number;
|
|
4
|
+
outputCostPerMToken: number;
|
|
5
|
+
};
|
|
6
|
+
declare const SCAN_OUTPUT_KEYS: readonly ["filesScanned", "jsonlFilesScanned", "jsonFilesScanned", "parseErrors", "nullInfoEventsSkipped", "duplicateEventsSkipped", "syntheticEventsSkipped", "zeroTotalEventsSkipped", "tokenEventsCounted", "unsupportedLegacyFiles", "activityOnlyDays"];
|
|
7
|
+
type Pricing = typeof FREE_MODEL_PRICING;
|
|
8
|
+
type ScanKey = (typeof SCAN_OUTPUT_KEYS)[number];
|
|
9
|
+
export interface CliArgs {
|
|
10
|
+
codexHome: string;
|
|
11
|
+
claudeConfigDir: string | null;
|
|
12
|
+
opencodeDir: string | null;
|
|
13
|
+
piAgentDir: string | null;
|
|
14
|
+
timezone: string;
|
|
15
|
+
outputHtml: string;
|
|
16
|
+
outputJson: string;
|
|
17
|
+
skipArchived: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface UsageTotals {
|
|
20
|
+
input_tokens: number;
|
|
21
|
+
cached_input_tokens: number;
|
|
22
|
+
output_tokens: number;
|
|
23
|
+
reasoning_output_tokens: number;
|
|
24
|
+
total_tokens: number;
|
|
25
|
+
}
|
|
26
|
+
interface CostBreakdown {
|
|
27
|
+
inputUSD: number;
|
|
28
|
+
cachedInputUSD: number;
|
|
29
|
+
outputUSD: number;
|
|
30
|
+
totalUSD: number;
|
|
31
|
+
}
|
|
32
|
+
interface ModelUsageAccumulator extends UsageTotals {
|
|
33
|
+
events: number;
|
|
34
|
+
is_fallback_model: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface DailyUsageAccumulator extends UsageTotals {
|
|
37
|
+
events: number;
|
|
38
|
+
model_usage: Record<string, ModelUsageAccumulator>;
|
|
39
|
+
}
|
|
40
|
+
export interface DailyReportRow {
|
|
41
|
+
date: string;
|
|
42
|
+
inputTokens: number;
|
|
43
|
+
cachedInputTokens: number;
|
|
44
|
+
outputTokens: number;
|
|
45
|
+
reasoningTokens: number;
|
|
46
|
+
totalTokens: number;
|
|
47
|
+
events: number;
|
|
48
|
+
costBreakdownUSD: CostBreakdown;
|
|
49
|
+
costUSD: number;
|
|
50
|
+
modelTotals: Record<string, number>;
|
|
51
|
+
modelBreakdown: Array<Record<string, unknown>>;
|
|
52
|
+
displayValue: number;
|
|
53
|
+
}
|
|
54
|
+
export interface MonthlyReportRow {
|
|
55
|
+
month: string;
|
|
56
|
+
inputTokens: number;
|
|
57
|
+
cachedInputTokens: number;
|
|
58
|
+
outputTokens: number;
|
|
59
|
+
reasoningTokens: number;
|
|
60
|
+
totalTokens: number;
|
|
61
|
+
events: number;
|
|
62
|
+
activeDays: number;
|
|
63
|
+
costBreakdownUSD: CostBreakdown;
|
|
64
|
+
costUSD: number;
|
|
65
|
+
modelTotals: Record<string, number>;
|
|
66
|
+
modelBreakdown: Array<Record<string, unknown>>;
|
|
67
|
+
}
|
|
68
|
+
interface ProviderReport {
|
|
69
|
+
providerId: string;
|
|
70
|
+
providerLabel: string;
|
|
71
|
+
providerShortLabel: string;
|
|
72
|
+
sourceHome: string | null;
|
|
73
|
+
days: DailyReportRow[];
|
|
74
|
+
monthly: MonthlyReportRow[];
|
|
75
|
+
pricing: {
|
|
76
|
+
source: string;
|
|
77
|
+
sourceLabel: string;
|
|
78
|
+
url: string;
|
|
79
|
+
missingModels: string[];
|
|
80
|
+
};
|
|
81
|
+
costTotalsUSD: CostBreakdown;
|
|
82
|
+
scan: Record<ScanKey, number>;
|
|
83
|
+
}
|
|
84
|
+
interface ProviderScanResult {
|
|
85
|
+
providerId: string;
|
|
86
|
+
providerLabel: string;
|
|
87
|
+
providerShortLabel: string;
|
|
88
|
+
sourceHome: string | null;
|
|
89
|
+
dailyUsage: Map<string, DailyUsageAccumulator>;
|
|
90
|
+
displayValuesByDay: Map<string, number>;
|
|
91
|
+
stats: Record<ScanKey, number>;
|
|
92
|
+
}
|
|
93
|
+
interface ResolvedPricing {
|
|
94
|
+
requestedModel: string;
|
|
95
|
+
resolvedModel: string | null;
|
|
96
|
+
pricing: Pricing;
|
|
97
|
+
isMissing: boolean;
|
|
98
|
+
isAlias: boolean;
|
|
99
|
+
source: string;
|
|
100
|
+
}
|
|
101
|
+
export declare function fetchLiteLLMPricingDataset(): Promise<Record<string, Record<string, unknown>>>;
|
|
102
|
+
export declare function resolveModelPricing(model: string, dataset: Record<string, Record<string, unknown>> | null): ResolvedPricing;
|
|
103
|
+
export declare function calculateCostBreakdown(usage: UsageTotals, pricing: Pricing): CostBreakdown;
|
|
104
|
+
export declare function providerScanHasUsage(scan: ProviderScanResult): boolean;
|
|
105
|
+
export declare function buildMonthlyRollups(reportDays: DailyReportRow[]): MonthlyReportRow[];
|
|
106
|
+
export declare function buildCombinedReport(providerReports: ProviderReport[]): ProviderReport;
|
|
107
|
+
export declare function buildReportPayload(providerScans: ProviderScanResult[], timeZone: string): Promise<Record<string, unknown>>;
|
|
108
|
+
export declare function writeOutput(report: Record<string, unknown>, outputHtml: string, outputJson: string): Promise<void>;
|
|
109
|
+
export declare function parseCliArgs(argv: string[]): CliArgs;
|
|
110
|
+
export declare function generateReport(args: CliArgs): Promise<Record<string, unknown>>;
|
|
111
|
+
export declare function main(argv?: string[]): Promise<void>;
|
|
112
|
+
export {};
|