opencode-cache-hit 0.1.0 → 0.2.1
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 +4 -2
- package/CONTRIBUTING.md +24 -8
- package/README.md +55 -22
- package/README.zh-CN.md +155 -92
- package/cache-hit.config.example.json +7 -2
- package/docs/assets/cache-hit-panel.v3.png +0 -0
- package/docs/en/design.md +30 -8
- package/docs/en/timeline-duplicate-writes.md +125 -0
- package/docs/en/timeline.md +26 -21
- package/docs/zh-CN/design.md +31 -9
- package/docs/zh-CN/timeline.md +28 -24
- package/package.json +1 -2
- package/scripts/README.md +64 -1
- package/scripts/plot-hit-rate.ts +4 -3
- package/scripts/timeline-dashboard.ts +728 -0
- package/src/agents-view.tsx +24 -10
- package/src/cache-ttl-view.tsx +128 -0
- package/src/format-cost.ts +83 -1
- package/src/format-model.ts +227 -0
- package/src/i18n.ts +18 -3
- package/src/load-config.ts +24 -5
- package/src/main-session-view.tsx +43 -3
- package/src/plugin-config.ts +59 -1
- package/src/plugin.tsx +4 -1
- package/src/pricing.ts +57 -0
- package/src/sidebar-host.tsx +13 -7
- package/src/stats.ts +6 -15
- package/src/timeline/collector.ts +40 -87
- package/src/timeline/records.ts +18 -29
- package/src/timeline/types.ts +3 -3
- package/src/timeline/writer.ts +5 -4
- package/src/tui-panel/README.md +2 -2
- package/src/tui-panel/README.zh-CN.md +2 -2
- package/src/tui-panel/components.tsx +31 -4
- package/src/tui-panel/index.ts +6 -1
- package/src/tui-panel/palette.ts +5 -0
- package/src/types.ts +16 -0
- package/src/use-cache-hit-metrics.ts +8 -9
- package/src/version.ts +4 -1
- package/src/widget.tsx +11 -3
- package/docs/assets/cache-hit-panel.png +0 -0
package/scripts/README.md
CHANGED
|
@@ -14,12 +14,75 @@ python3 -c "import json,sys; r=[json.loads(x) for x in open(sys.argv[1]) if x.st
|
|
|
14
14
|
bun -e "const t=await Bun.file(process.argv[1]).text();const rows=t.trim().split('\n').filter(Boolean).map(l=>JSON.parse(l));const h=rows.map(r=>r.hitPercent).filter((p):p is number=>p!=null);console.log(rows.length+' calls, avg hit '+(h.reduce((a,b)=>a+b,0)/h.length).toFixed(1)+'%')" logs/timeline-2026-05-31.jsonl
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Export TSV for spreadsheets:
|
|
17
|
+
Export TSV for spreadsheets (time fields are ISO 8601 strings):
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
jq -r 'select(.hitPercent!=null) | [.completedAt,.scope,.hitPercent,.cost]|@tsv' logs/timeline-2026-05-31.jsonl
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## `timeline-dashboard.ts` (Bun, no install)
|
|
24
|
+
|
|
25
|
+
Interactive HTML dashboard with charts, filters, and data tables:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
bun scripts/timeline-dashboard.ts # auto-detect logs/ (no browser)
|
|
29
|
+
bun scripts/timeline-dashboard.ts --open # write HTML, then open browser
|
|
30
|
+
bun scripts/timeline-dashboard.ts -o /tmp/report.html # custom output path
|
|
31
|
+
bun scripts/timeline-dashboard.ts ~/logs/timeline-*.jsonl # globs expanded by script
|
|
32
|
+
bun scripts/timeline-dashboard.ts --output /tmp/report.html --open # combined
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Default output: `/tmp/timeline-dashboard-YYYY-MM-DD-HHmmss.html` (timestamp suffix to avoid overwrites).
|
|
36
|
+
|
|
37
|
+
**Browser:** not opened by default; pass `--open` (macOS `open`, Linux `xdg-open`, Windows `start`).
|
|
38
|
+
|
|
39
|
+
**Features:**
|
|
40
|
+
- Summary cards follow active filters (records, tokens, cost, avg hit rate)
|
|
41
|
+
- Time / session / scope / model / text search filters
|
|
42
|
+
- 3 Chart.js charts: token volume (stacked bar), hit rate + cost (dual axis), duration (bar)
|
|
43
|
+
- Session summary table (mixed main+child scope shown as `main+child`)
|
|
44
|
+
- Per-call detail table with expandable rows (all JSONL fields)
|
|
45
|
+
- Embedded data — no server needed, just open the HTML file
|
|
46
|
+
|
|
47
|
+
**How it works:**
|
|
48
|
+
|
|
49
|
+
1. Reads `timeline-*.jsonl` and rotation backups `timeline-*.jsonl.N` from the default log dir (`~/.local/share/opencode/logs/cache-hit/`) or user-supplied paths/globs
|
|
50
|
+
2. Parses each JSONL line (`schema: 1` validation), sorts by `completedAt` / `created`
|
|
51
|
+
3. Aggregates per-session statistics in the browser when filters change
|
|
52
|
+
4. Generates a self-contained HTML file with:
|
|
53
|
+
- All data embedded as JSON in a `<script>` tag (`<` escaped for safety)
|
|
54
|
+
- Chart.js 4.4.7 from CDN (`cdn.jsdelivr.net`)
|
|
55
|
+
- Vanilla JS for interactivity (no framework dependency)
|
|
56
|
+
5. Optional `--open` opens the output file in the default browser
|
|
57
|
+
|
|
58
|
+
**Avg hit rate:** excludes `skippedForHit` rows (same rule as `plot-hit-rate.ts`); null `hitPercent` still appear in tables/charts.
|
|
59
|
+
|
|
60
|
+
**Cost display:** reads `currency` / `costUnit` / `rate` from `~/.config/opencode/cache-hit.json` when present (same as the TUI sidebar). **No config file** → defaults (`CNY` display, `USD` JSONL unit, rate `6.77`). Invalid or partial cost fields are normalized; corrupt config falls back without failing the script. JSONL always stores raw `cost` in `costUnit` (usually USD).
|
|
61
|
+
|
|
62
|
+
**Note:** The generated HTML is self-contained except Chart.js CDN. Re-run the script to refresh data (static snapshot).
|
|
63
|
+
|
|
64
|
+
### Design approaches
|
|
65
|
+
|
|
66
|
+
**Option A (current — static HTML):**
|
|
67
|
+
Data is embedded into the HTML at build time by Bun. The browser just renders.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
bun scripts/timeline-dashboard.ts → /tmp/timeline-dashboard-YYYY-MM-DD-HHmmss.html (self-contained)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- Pros: No server needed, zero runtime deps, can email/share the file
|
|
74
|
+
- Cons: Snapshot only — re-run to refresh data
|
|
75
|
+
|
|
76
|
+
**Option B (live server):**
|
|
77
|
+
Starts an HTTP server; the browser fetches JSONL via `fetch("/api/logs")`.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
bun scripts/timeline-dashboard.ts serve → http://localhost:PORT
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- Pros: Live reload — refresh the page to see new logs
|
|
84
|
+
- Cons: Must keep a process running, cannot send the page as a file
|
|
85
|
+
|
|
23
86
|
## `plot-hit-rate.ts` (Bun, no install)
|
|
24
87
|
|
|
25
88
|
Terminal ASCII chart; optional SVG (`open /tmp/hit.svg`):
|
package/scripts/plot-hit-rate.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
type Row = {
|
|
11
11
|
rootSessionId?: string
|
|
12
12
|
scope?: string
|
|
13
|
-
created?:
|
|
14
|
-
completedAt?:
|
|
13
|
+
created?: string
|
|
14
|
+
completedAt?: string
|
|
15
15
|
hitPercent?: number | null
|
|
16
16
|
skippedForHit?: boolean
|
|
17
17
|
}
|
|
@@ -57,7 +57,8 @@ async function loadRecords(path: string, root?: string): Promise<Row[]> {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function timeOf(r: Row): number {
|
|
60
|
-
|
|
60
|
+
const ts = r.completedAt ?? r.created
|
|
61
|
+
return ts ? new Date(ts).getTime() : 0
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
function groupByRoot(rows: Row[]): Map<string, Row[]> {
|