token-optimizer-opencode 1.0.5 → 1.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/dashboard/generator.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA6BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CA0RhE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAQ7D"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/dashboard/generator.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA6BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CA6UhE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAQ7D"}
@@ -3,6 +3,7 @@ import { join, dirname } from "node:path";
3
3
  import { randomBytes } from "node:crypto";
4
4
  import { TrendsStore } from "../storage/trends.js";
5
5
  import { scoreToGrade, scoreToBand } from "../util/grade.js";
6
+ import { computeRealizedSavings } from "../savings.js";
6
7
  function esc(s) {
7
8
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
8
9
  }
@@ -40,6 +41,9 @@ export function generateDashboard(opts) {
40
41
  finally {
41
42
  store.close();
42
43
  }
44
+ // Realized before/after savings (opens its own short-lived store connection).
45
+ const savings = computeRealizedSavings(opts.dataDir, days);
46
+ const fmtCost = (n) => !Number.isFinite(n) ? "$0" : n >= 1000 ? `$${(n / 1000).toFixed(1)}k` : `$${n.toFixed(2)}`;
43
47
  const totalSessions = sessions.length;
44
48
  const avgRH = totalSessions > 0
45
49
  ? sessions.reduce((s, r) => s + num(r.resource_health), 0) / totalSessions
@@ -126,6 +130,7 @@ tr:hover td { background: var(--bg-hover); }
126
130
 
127
131
  <div class="nav">
128
132
  <a class="active" data-view="overview">Overview</a>
133
+ <a data-view="savings">Savings</a>
129
134
  <a data-view="quality">Quality Trends</a>
130
135
  <a data-view="sessions">Sessions</a>
131
136
  <a data-view="daily">Daily Stats</a>
@@ -189,6 +194,51 @@ tr:hover td { background: var(--bg-hover); }
189
194
  ` : ""}
190
195
  </div>
191
196
 
197
+ <!-- SAVINGS -->
198
+ <div class="view" id="view-savings">
199
+ <div class="section-title">Realized Savings</div>
200
+ ${!savings.ready ? `
201
+ <div class="empty">
202
+ Realized savings need a baseline of your early usage to compare against.<br>
203
+ <span style="font-size:13px">${esc(savings.status)}</span>
204
+ </div>
205
+ <div class="stat-sub" style="margin-top:var(--s-4)">This measures your actual cost-per-session drop over time, priced from your recorded spend. Until the baseline is set, the Sessions view shows current usage.</div>
206
+ ` : `
207
+ <div class="stats">
208
+ <div class="stat">
209
+ <div class="stat-value" style="color:var(--success)">${fmtCost(Math.max(0, savings.monthlySavingsUsd))}</div>
210
+ <div class="stat-label">Est. Monthly Savings</div>
211
+ <div class="stat-sub">${savings.installDate ? "since " + esc(savings.installDate) : ""}</div>
212
+ </div>
213
+ <div class="stat">
214
+ <div class="stat-value">${fmtCost(savings.beforeCostPerSession)} &rarr; ${fmtCost(savings.afterCostPerSession)}</div>
215
+ <div class="stat-label">Cost / Session</div>
216
+ <div class="stat-sub">${savings.savingsPerSession >= 0 ? "&minus;" : "+"}${fmtCost(Math.abs(savings.savingsPerSession))}/session</div>
217
+ </div>
218
+ <div class="stat">
219
+ <div class="stat-value">${fmtCost(savings.cumulativeSavedUsd)}</div>
220
+ <div class="stat-label">Saved So Far</div>
221
+ <div class="stat-sub">across all sessions since baseline</div>
222
+ </div>
223
+ <div class="stat">
224
+ <div class="stat-value" style="font-size:18px">${esc(savings.beforeMixLabel)} &rarr; ${esc(savings.afterMixLabel)}</div>
225
+ <div class="stat-label">Model Mix Shift</div>
226
+ <div class="stat-sub">~${Math.round(savings.sessionsPerMonth)} sessions/mo</div>
227
+ </div>
228
+ </div>
229
+ <div class="section-title">Where the savings come from</div>
230
+ <table>
231
+ <thead><tr><th>Lever</th><th>Est. $/month</th></tr></thead>
232
+ <tbody>
233
+ ${savings.breakdown.filter((b) => Math.abs(b.monthlyUsd) >= 0.005).map((b) => `<tr>
234
+ <td>${esc(b.label)}</td>
235
+ <td style="font-family:monospace;color:${b.monthlyUsd >= 0 ? "var(--success)" : "var(--danger)"}">${b.monthlyUsd >= 0 ? "" : "+"}${fmtCost(Math.abs(b.monthlyUsd))}/mo</td>
236
+ </tr>`).join("")}
237
+ </tbody>
238
+ </table>
239
+ `}
240
+ </div>
241
+
192
242
  <!-- QUALITY TRENDS -->
193
243
  <div class="view" id="view-quality">
194
244
  <div class="section-title">Quality Score Trends</div>
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/dashboard/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/dashboard/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface SavingsBreakdownItem {
2
+ key: string;
3
+ label: string;
4
+ monthlyUsd: number;
5
+ }
6
+ export interface RealizedSavings {
7
+ ready: boolean;
8
+ status: string;
9
+ monthlySavingsUsd: number;
10
+ savingsPerSession: number;
11
+ beforeCostPerSession: number;
12
+ afterCostPerSession: number;
13
+ sessionsPerMonth: number;
14
+ beforeMixLabel: string;
15
+ afterMixLabel: string;
16
+ cumulativeSavedUsd: number;
17
+ installDate: string | null;
18
+ breakdown: SavingsBreakdownItem[];
19
+ }
20
+ /**
21
+ * Compute realized before/after savings from trends.db. `now` is injectable for
22
+ * testing; `rowsOverride` lets tests bypass the DB entirely.
23
+ */
24
+ export declare function computeRealizedSavings(dataDir: string, days?: number, now?: number, rowsOverride?: Array<Record<string, unknown>>): RealizedSavings;
25
+ //# sourceMappingURL=savings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"savings.d.ts","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"AA4DA,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AAqED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAW,EACjB,GAAG,GAAE,MAAmB,EACxB,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC5C,eAAe,CAgFjB"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Realized savings engine for OpenCode (the "$11/session -> $3/session" delta).
3
+ *
4
+ * Parity with the Claude Code / Codex / OpenClaw before/after methodology:
5
+ * freeze an early-usage baseline, compare it to current usage, report the
6
+ * per-session cost delta. OpenCode already persists every session to trends.db
7
+ * (session_log), so this reads that durable store directly -- no extra
8
+ * persistence, and the baseline is recomputed deterministically from the fixed
9
+ * historical window (no freeze needed; the early window never changes once past).
10
+ *
11
+ * MULTI-MODEL CORRECTNESS: OpenCode runs many models with very different pricing.
12
+ * Each session_log row already carries cost_usd computed at ITS OWN model when
13
+ * recorded, so the per-session mean is exact regardless of model mix -- no
14
+ * blended-average-vector approximation. The waterfall uses the era's effective
15
+ * $/token (real cost / real tokens), which encodes the mix, and telescopes
16
+ * exactly to the headline delta.
17
+ *
18
+ * Distinct from forward-looking waste detection: this measures what you HAVE
19
+ * saved, against an early baseline, using your actual recorded spend.
20
+ */
21
+ import { TrendsStore } from "./storage/trends.js";
22
+ // Constants mirror the other platforms' baseline tunables.
23
+ const BASELINE_ONBOARDING_DAYS = 1;
24
+ const BASELINE_EARLY_WINDOW_DAYS = 30;
25
+ const BASELINE_MIN_STABLE_SESSIONS = 30;
26
+ const AFTER_MIN_SESSIONS = 10;
27
+ const WINSOR_PCT = 0.99;
28
+ const WINSOR_MIN_SAMPLE = 10;
29
+ const DAY_MS = 86_400_000;
30
+ function num(v) {
31
+ const n = typeof v === "number" ? v : parseFloat(String(v));
32
+ return Number.isFinite(n) ? n : 0;
33
+ }
34
+ function toRec(row) {
35
+ const ts = num(row.created_at) > 0
36
+ ? num(row.created_at) * 1000
37
+ : Date.parse(String(row.date ?? "")) || 0;
38
+ return {
39
+ ts,
40
+ model: String(row.model ?? "unknown"),
41
+ tokens: num(row.tokens_input) +
42
+ num(row.tokens_output) +
43
+ num(row.tokens_cache_read) +
44
+ num(row.tokens_cache_write),
45
+ cost: num(row.cost_usd),
46
+ };
47
+ }
48
+ function mixLabel(shares) {
49
+ const top = Object.entries(shares).sort((a, b) => b[1] - a[1])[0];
50
+ return top ? `${Math.round(top[1] * 100)}% ${top[0]}` : "n/a";
51
+ }
52
+ /** Winsorize the top 1% of sessions by cost (scale cost AND tokens together so
53
+ * the effective rate stays consistent), then aggregate. */
54
+ function computeEra(recs) {
55
+ const n = recs.length;
56
+ if (n === 0)
57
+ return { n: 0, costPerSession: 0, meanTokens: 0, effRate: 0, shares: {} };
58
+ let cap = Infinity;
59
+ if (n >= WINSOR_MIN_SAMPLE) {
60
+ const costs = recs.map((r) => r.cost).sort((a, b) => a - b);
61
+ // floor (not round): round((n-1)*0.99) == n-1 for n<=51, making the cap the
62
+ // max element and winsorization a no-op for every minimum-sample window.
63
+ // Clamp to <= n-2 so the single largest session is always above the cap.
64
+ cap = costs[Math.min(n - 2, Math.floor((n - 1) * WINSOR_PCT))];
65
+ }
66
+ let costSum = 0;
67
+ let tokSum = 0;
68
+ const byModel = {};
69
+ let modelTotal = 0;
70
+ for (const r of recs) {
71
+ const scale = r.cost > cap && r.cost > 0 ? cap / r.cost : 1;
72
+ costSum += r.cost * scale;
73
+ tokSum += r.tokens * scale;
74
+ byModel[r.model] = (byModel[r.model] ?? 0) + r.tokens;
75
+ modelTotal += r.tokens;
76
+ }
77
+ const shares = {};
78
+ if (modelTotal > 0) {
79
+ for (const [m, t] of Object.entries(byModel))
80
+ shares[m] = t / modelTotal;
81
+ }
82
+ return {
83
+ n,
84
+ costPerSession: costSum / n,
85
+ meanTokens: tokSum / n,
86
+ effRate: tokSum > 0 ? costSum / tokSum : 0,
87
+ shares,
88
+ };
89
+ }
90
+ const NOT_READY = (status) => ({
91
+ ready: false,
92
+ status,
93
+ monthlySavingsUsd: 0,
94
+ savingsPerSession: 0,
95
+ beforeCostPerSession: 0,
96
+ afterCostPerSession: 0,
97
+ sessionsPerMonth: 0,
98
+ beforeMixLabel: "n/a",
99
+ afterMixLabel: "n/a",
100
+ cumulativeSavedUsd: 0,
101
+ installDate: null,
102
+ breakdown: [],
103
+ });
104
+ /**
105
+ * Compute realized before/after savings from trends.db. `now` is injectable for
106
+ * testing; `rowsOverride` lets tests bypass the DB entirely.
107
+ */
108
+ export function computeRealizedSavings(dataDir, days = 30, now = Date.now(), rowsOverride) {
109
+ let rows = rowsOverride ?? [];
110
+ if (!rowsOverride) {
111
+ const store = new TrendsStore(dataDir);
112
+ try {
113
+ rows = store.getAllSessions();
114
+ }
115
+ catch {
116
+ rows = [];
117
+ }
118
+ finally {
119
+ store.close();
120
+ }
121
+ }
122
+ const history = rows.map(toRec).filter((r) => r.ts > 0).sort((a, b) => a.ts - b.ts);
123
+ if (history.length === 0)
124
+ return NOT_READY("no sessions yet");
125
+ const installTs = history[0].ts;
126
+ const installDate = new Date(installTs).toISOString().slice(0, 10);
127
+ const windowStart = installTs + BASELINE_ONBOARDING_DAYS * DAY_MS;
128
+ const windowEnd = windowStart + BASELINE_EARLY_WINDOW_DAYS * DAY_MS;
129
+ const before = history.filter((r) => r.ts >= windowStart && r.ts < windowEnd);
130
+ if (before.length < BASELINE_MIN_STABLE_SESSIONS) {
131
+ const r = NOT_READY(`building baseline (${before.length}/${BASELINE_MIN_STABLE_SESSIONS} early sessions)`);
132
+ r.installDate = installDate;
133
+ return r;
134
+ }
135
+ if (now < windowEnd) {
136
+ const daysLeft = Math.ceil((windowEnd - now) / DAY_MS);
137
+ const r = NOT_READY(`building baseline (${daysLeft}d of early window left)`);
138
+ r.installDate = installDate;
139
+ return r;
140
+ }
141
+ // After = recent sessions in lookback, strictly after the baseline window.
142
+ const afterStart = Math.max(windowEnd, now - days * DAY_MS);
143
+ const after = history.filter((r) => r.ts >= afterStart);
144
+ const bs = computeEra(before);
145
+ if (after.length < AFTER_MIN_SESSIONS) {
146
+ const r = NOT_READY(`building comparison (${after.length}/${AFTER_MIN_SESSIONS} recent sessions)`);
147
+ r.installDate = installDate;
148
+ r.beforeCostPerSession = bs.costPerSession;
149
+ r.beforeMixLabel = mixLabel(bs.shares);
150
+ return r;
151
+ }
152
+ const as = computeEra(after);
153
+ const perSession = bs.costPerSession - as.costPerSession;
154
+ const afterWindowDays = Math.max(1, (now - afterStart) / DAY_MS);
155
+ const sessionsPerMonth = (after.length / afterWindowDays) * 30;
156
+ const monthly = perSession * sessionsPerMonth;
157
+ const allAfter = history.filter((r) => r.ts >= windowEnd);
158
+ const cumulative = perSession * allAfter.length;
159
+ // 2-lever waterfall (telescopes exactly to perSession):
160
+ // routing/mix = (effRate_before - effRate_after) * meanTokens_before
161
+ // volume = effRate_after * (meanTokens_before - meanTokens_after)
162
+ const perMonth = (x) => x * sessionsPerMonth;
163
+ const routing = (bs.effRate - as.effRate) * bs.meanTokens;
164
+ const volume = as.effRate * (bs.meanTokens - as.meanTokens);
165
+ const breakdown = [
166
+ { key: "routing", label: "Model routing & pricing", monthlyUsd: perMonth(routing) },
167
+ { key: "volume", label: "Token volume", monthlyUsd: perMonth(volume) },
168
+ ];
169
+ return {
170
+ ready: true,
171
+ status: "ok",
172
+ monthlySavingsUsd: monthly,
173
+ savingsPerSession: perSession,
174
+ beforeCostPerSession: bs.costPerSession,
175
+ afterCostPerSession: as.costPerSession,
176
+ sessionsPerMonth,
177
+ beforeMixLabel: mixLabel(bs.shares),
178
+ afterMixLabel: mixLabel(as.shares),
179
+ cumulativeSavedUsd: cumulative,
180
+ installDate,
181
+ breakdown,
182
+ };
183
+ }
184
+ //# sourceMappingURL=savings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"savings.js","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,9 @@ export declare class TrendsStore {
22
22
  close(): void;
23
23
  recordSession(data: SessionTrendData): void;
24
24
  getRecentSessions(days?: number): Array<Record<string, unknown>>;
25
+ /** All sessions ever recorded, oldest-first. Used to establish the realized-
26
+ * savings baseline (the earliest stable usage window). */
27
+ getAllSessions(): Array<Record<string, unknown>>;
25
28
  getDailyStats(days?: number): Array<Record<string, unknown>>;
26
29
  }
27
30
  //# sourceMappingURL=trends.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trends.d.ts","sourceRoot":"","sources":["../../src/storage/trends.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM;IAQ3B,OAAO,CAAC,OAAO;IAUf,KAAK,IAAI,IAAI;IAOb,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAwC3C,iBAAiB,CAAC,IAAI,GAAE,MAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAWpE,aAAa,CAAC,IAAI,GAAE,MAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAqBjE"}
1
+ {"version":3,"file":"trends.d.ts","sourceRoot":"","sources":["../../src/storage/trends.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM;IAQ3B,OAAO,CAAC,OAAO;IAUf,KAAK,IAAI,IAAI;IAOb,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAwC3C,iBAAiB,CAAC,IAAI,GAAE,MAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAWpE;+DAC2D;IAC3D,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAOhD,aAAa,CAAC,IAAI,GAAE,MAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAqBjE"}
@@ -92,6 +92,14 @@ export class TrendsStore {
92
92
  .query("SELECT * FROM session_log WHERE date >= ? ORDER BY created_at DESC")
93
93
  .all(cutoffStr);
94
94
  }
95
+ /** All sessions ever recorded, oldest-first. Used to establish the realized-
96
+ * savings baseline (the earliest stable usage window). */
97
+ getAllSessions() {
98
+ const db = this.connect();
99
+ return db
100
+ .query("SELECT * FROM session_log ORDER BY created_at ASC")
101
+ .all();
102
+ }
95
103
  getDailyStats(days = 30) {
96
104
  const db = this.connect();
97
105
  const cutoff = new Date();
@@ -1 +1 @@
1
- {"version":3,"file":"trends.js","sourceRoot":"","sources":["../../src/storage/trends.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trends.js","sourceRoot":"","sources":["../../src/storage/trends.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,7 @@ export function createTokenStatusTool(getState) {
22
22
  "",
23
23
  `**Resource Health**: ${Math.round(q.resourceHealth)}/100 (${q.resourceHealthGrade})`,
24
24
  `**Session Efficiency**: ${Math.round(q.sessionEfficiency)}/100 (${q.sessionEfficiencyGrade})`,
25
- `**Context Fill**: ${Math.round(q.fillPct * 100)}% | **Band**: ${scoreToBand(q.resourceHealth)}`,
25
+ `**Context Fill**: ~${Math.round(q.fillPct * 100)}% est. (vs assumed window) | **Band**: ${scoreToBand(q.resourceHealth)}`,
26
26
  `**Activity Mode**: ${mode}`,
27
27
  `**Tool Calls**: ${q.toolCalls} | **Compactions**: ${state.store.getCompactionCount()}`,
28
28
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"token-status.js","sourceRoot":"","sources":["../../src/tools/token-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,UAAU,qBAAqB,CAAC,QAIrC;IACC,OAAO,IAAI,CAAC;QACV,WAAW,EACT,+FAA+F;YAC/F,sGAAsG;QACxG,IAAI,EAAE;YACJ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;SAClF;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;YAEzB,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACvC,OAAO;oBACL,KAAK,EAAE,cAAc;oBACrB,MAAM,EAAE,kFAAkF;iBAC3F,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;YAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;YAE9D,MAAM,KAAK,GAAa;gBACtB,0BAA0B;gBAC1B,EAAE;gBACF,wBAAwB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,mBAAmB,GAAG;gBACrF,2BAA2B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,sBAAsB,GAAG;gBAC9F,qBAAqB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,iBAAiB,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE;gBAChG,sBAAsB,IAAI,EAAE;gBAC5B,mBAAmB,CAAC,CAAC,SAAS,uBAAuB,KAAK,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE;aACxF,CAAC;YAEF,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,KAAK,OAAO,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;gBAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;oBACrD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC5C,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,MAAM,EAAE,CAAC,KAAK,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;YAED,OAAO;gBACL,KAAK,EAAE,cAAc;gBACrB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACzB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"token-status.js","sourceRoot":"","sources":["../../src/tools/token-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,UAAU,qBAAqB,CAAC,QAIrC;IACC,OAAO,IAAI,CAAC;QACV,WAAW,EACT,+FAA+F;YAC/F,sGAAsG;QACxG,IAAI,EAAE;YACJ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;SAClF;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;YAEzB,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACvC,OAAO;oBACL,KAAK,EAAE,cAAc;oBACrB,MAAM,EAAE,kFAAkF;iBAC3F,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;YAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;YAE9D,MAAM,KAAK,GAAa;gBACtB,0BAA0B;gBAC1B,EAAE;gBACF,wBAAwB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,mBAAmB,GAAG;gBACrF,2BAA2B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,sBAAsB,GAAG;gBAC9F,sBAAsB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,0CAA0C,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE;gBAC1H,sBAAsB,IAAI,EAAE;gBAC5B,mBAAmB,CAAC,CAAC,SAAS,uBAAuB,KAAK,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE;aACxF,CAAC;YAEF,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,KAAK,OAAO,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;gBAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;oBACrD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC5C,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,MAAM,EAAE,CAAC,KAAK,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;YAED,OAAO;gBACL,KAAK,EAAE,cAAc;gBACrB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACzB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-window.d.ts","sourceRoot":"","sources":["../../src/util/context-window.ts"],"names":[],"mappings":"AA8EA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAa3D"}
1
+ {"version":3,"file":"context-window.d.ts","sourceRoot":"","sources":["../../src/util/context-window.ts"],"names":[],"mappings":"AA8EA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAkB3D"}
@@ -74,6 +74,11 @@ export function contextWindowForModel(model) {
74
74
  const direct = MODEL_CONTEXT_WINDOWS[lower];
75
75
  if (direct !== undefined)
76
76
  return direct;
77
+ // Legacy Claude (2.x/3.x) is genuinely 200K. Guard before the substring loop,
78
+ // which would otherwise match the bare "opus"/"sonnet" keys and over-promote
79
+ // e.g. "claude-3-5-sonnet-20241022" to 1M (understating fill).
80
+ if (lower.includes("claude-2") || lower.includes("claude-3"))
81
+ return 200_000;
77
82
  for (const [key, value] of Object.entries(MODEL_CONTEXT_WINDOWS)) {
78
83
  if (lower.includes(key))
79
84
  return value;
@@ -1 +1 @@
1
- {"version":3,"file":"context-window.js","sourceRoot":"","sources":["../../src/util/context-window.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAA2B;IACpD,qDAAqD;IACrD,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,OAAO;IACd,iBAAiB,EAAE,SAAS;IAC5B,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,kBAAkB,EAAE,OAAO;IAE3B,sBAAsB;IACtB,aAAa,EAAE,SAAS;IACxB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,SAAS;IACpB,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,OAAO;IACvB,eAAe,EAAE,OAAO;IACxB,eAAe,EAAE,OAAO;IACxB,SAAS,EAAE,OAAO;IAClB,oBAAoB,EAAE,OAAO;IAC7B,eAAe,EAAE,OAAO;IACxB,SAAS,EAAE,OAAO;IAClB,aAAa,EAAE,OAAO;IACtB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE,OAAO;IACrB,YAAY,EAAE,OAAO;IACrB,sBAAsB;IACtB,SAAS,EAAE,SAAS;IACpB,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,SAAS;IACzB,QAAQ,EAAE,OAAO;IACjB,aAAa,EAAE,OAAO;IACtB,mBAAmB;IACnB,EAAE,EAAE,OAAO;IACX,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,OAAO;IACjB,SAAS,EAAE,OAAO;IAElB,gBAAgB;IAChB,kBAAkB,EAAE,SAAS;IAC7B,wBAAwB,EAAE,SAAS;IACnC,uBAAuB,EAAE,SAAS;IAClC,cAAc,EAAE,SAAS;IACzB,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAClC,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAElC,WAAW;IACX,aAAa,EAAE,OAAO;IACtB,aAAa,EAAE,OAAO;IAEtB,OAAO;IACP,KAAK,EAAE,OAAO;IACd,YAAY,EAAE,OAAO;IACrB,YAAY,EAAE,OAAO;IAErB,UAAU;IACV,eAAe,EAAE,OAAO;IACxB,eAAe,EAAE,OAAO;IAExB,MAAM;IACN,QAAQ,EAAE,OAAO;IAEjB,QAAQ;IACR,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,OAAO;IACpB,SAAS,EAAE,OAAO;IAClB,eAAe,EAAE,OAAO;IACxB,YAAY,EAAE,OAAO;IACrB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,sBAAsB,CAAC;IAE1C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAElC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAExC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IACxC,CAAC;IAED,OAAO,sBAAsB,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"context-window.js","sourceRoot":"","sources":["../../src/util/context-window.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAA2B;IACpD,qDAAqD;IACrD,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,OAAO;IACd,iBAAiB,EAAE,SAAS;IAC5B,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,kBAAkB,EAAE,OAAO;IAE3B,sBAAsB;IACtB,aAAa,EAAE,SAAS;IACxB,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,SAAS;IACpB,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,OAAO;IACvB,eAAe,EAAE,OAAO;IACxB,eAAe,EAAE,OAAO;IACxB,SAAS,EAAE,OAAO;IAClB,oBAAoB,EAAE,OAAO;IAC7B,eAAe,EAAE,OAAO;IACxB,SAAS,EAAE,OAAO;IAClB,aAAa,EAAE,OAAO;IACtB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE,OAAO;IACrB,YAAY,EAAE,OAAO;IACrB,sBAAsB;IACtB,SAAS,EAAE,SAAS;IACpB,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,SAAS;IACzB,QAAQ,EAAE,OAAO;IACjB,aAAa,EAAE,OAAO;IACtB,mBAAmB;IACnB,EAAE,EAAE,OAAO;IACX,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,OAAO;IACjB,SAAS,EAAE,OAAO;IAElB,gBAAgB;IAChB,kBAAkB,EAAE,SAAS;IAC7B,wBAAwB,EAAE,SAAS;IACnC,uBAAuB,EAAE,SAAS;IAClC,cAAc,EAAE,SAAS;IACzB,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAClC,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAElC,WAAW;IACX,aAAa,EAAE,OAAO;IACtB,aAAa,EAAE,OAAO;IAEtB,OAAO;IACP,KAAK,EAAE,OAAO;IACd,YAAY,EAAE,OAAO;IACrB,YAAY,EAAE,OAAO;IAErB,UAAU;IACV,eAAe,EAAE,OAAO;IACxB,eAAe,EAAE,OAAO;IAExB,MAAM;IACN,QAAQ,EAAE,OAAO;IAEjB,QAAQ;IACR,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,OAAO;IACpB,SAAS,EAAE,OAAO;IAClB,eAAe,EAAE,OAAO;IACxB,YAAY,EAAE,OAAO;IACrB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,sBAAsB,CAAC;IAE1C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAElC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAExC,8EAA8E;IAC9E,6EAA6E;IAC7E,+DAA+D;IAC/D,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,OAAO,CAAC;IAE7E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IACxC,CAAC;IAED,OAAO,sBAAsB,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-optimizer-opencode",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Context quality scoring, smart compaction, and session continuity for OpenCode. Full parity with the Claude Code Token Optimizer plugin.",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",