@leo000001/opencode-quota-sidebar 2.0.14 → 2.0.15

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/dist/cost.d.ts CHANGED
@@ -16,6 +16,9 @@ export type ModelCostRates = {
16
16
  };
17
17
  export declare function modelCostKey(providerID: string, modelID: string): string;
18
18
  export declare function modelCostLookupKeys(providerID: string, modelID: string): string[];
19
+ export declare function getBundledModelCostMap(): {
20
+ [x: string]: ModelCostRates;
21
+ };
19
22
  export declare function parseModelCostRates(value: unknown): ModelCostRates | undefined;
20
23
  export declare function guessModelCostDivisor(rates: ModelCostRates): 1 | 1000000;
21
24
  export declare function cacheCoverageModeFromRates(rates: ModelCostRates | undefined): CacheCoverageMode;
package/dist/cost.js CHANGED
@@ -75,6 +75,100 @@ export function canonicalApiCostProviderID(providerID) {
75
75
  }
76
76
  return normalized;
77
77
  }
78
+ function anthropicPricing(input, output, options) {
79
+ // OpenCode currently reports zero Anthropic model prices in runtime metadata,
80
+ // so keep a bundled fallback sourced from Anthropic's pricing docs.
81
+ return {
82
+ input,
83
+ output,
84
+ cacheRead: input * 0.1,
85
+ // OpenCode only exposes aggregate cache.write tokens, so use Anthropic's
86
+ // default 5-minute prompt-caching write rate.
87
+ cacheWrite: input * 1.25,
88
+ contextOver200k: options?.longContextInput !== undefined &&
89
+ options?.longContextOutput !== undefined
90
+ ? {
91
+ input: options.longContextInput,
92
+ output: options.longContextOutput,
93
+ cacheRead: options.longContextInput * 0.1,
94
+ cacheWrite: options.longContextInput * 1.25,
95
+ }
96
+ : undefined,
97
+ };
98
+ }
99
+ const BUNDLED_MODEL_COST_RATES = [
100
+ {
101
+ providerID: 'anthropic',
102
+ modelID: 'claude-opus-4-6',
103
+ rates: anthropicPricing(5, 25),
104
+ },
105
+ {
106
+ providerID: 'anthropic',
107
+ modelID: 'claude-opus-4-5',
108
+ rates: anthropicPricing(5, 25),
109
+ },
110
+ {
111
+ providerID: 'anthropic',
112
+ modelID: 'claude-opus-4-1',
113
+ rates: anthropicPricing(15, 75),
114
+ },
115
+ {
116
+ providerID: 'anthropic',
117
+ modelID: 'claude-opus-4',
118
+ rates: anthropicPricing(15, 75),
119
+ },
120
+ {
121
+ providerID: 'anthropic',
122
+ modelID: 'claude-sonnet-4-6',
123
+ rates: anthropicPricing(3, 15),
124
+ },
125
+ {
126
+ providerID: 'anthropic',
127
+ modelID: 'claude-sonnet-4-5',
128
+ rates: anthropicPricing(3, 15, {
129
+ longContextInput: 6,
130
+ longContextOutput: 22.5,
131
+ }),
132
+ },
133
+ {
134
+ providerID: 'anthropic',
135
+ modelID: 'claude-sonnet-4',
136
+ rates: anthropicPricing(3, 15, {
137
+ longContextInput: 6,
138
+ longContextOutput: 22.5,
139
+ }),
140
+ },
141
+ {
142
+ providerID: 'anthropic',
143
+ modelID: 'claude-3-7-sonnet',
144
+ rates: anthropicPricing(3, 15),
145
+ },
146
+ {
147
+ providerID: 'anthropic',
148
+ modelID: 'claude-3-5-sonnet',
149
+ rates: anthropicPricing(3, 15),
150
+ },
151
+ {
152
+ providerID: 'anthropic',
153
+ modelID: 'claude-haiku-4-5',
154
+ rates: anthropicPricing(1, 5),
155
+ },
156
+ {
157
+ providerID: 'anthropic',
158
+ modelID: 'claude-3-5-haiku',
159
+ rates: anthropicPricing(0.8, 4),
160
+ },
161
+ {
162
+ providerID: 'anthropic',
163
+ modelID: 'claude-3-opus',
164
+ rates: anthropicPricing(15, 75),
165
+ },
166
+ {
167
+ providerID: 'anthropic',
168
+ modelID: 'claude-3-haiku',
169
+ rates: anthropicPricing(0.25, 1.25),
170
+ },
171
+ ];
78
172
  export function modelCostKey(providerID, modelID) {
79
173
  return `${providerID}:${modelID}`;
80
174
  }
@@ -101,6 +195,19 @@ export function modelCostLookupKeys(providerID, modelID) {
101
195
  }
102
196
  return keys;
103
197
  }
198
+ function createBundledModelCostMap() {
199
+ const map = {};
200
+ for (const entry of BUNDLED_MODEL_COST_RATES) {
201
+ for (const key of modelCostLookupKeys(entry.providerID, entry.modelID)) {
202
+ map[key] = entry.rates;
203
+ }
204
+ }
205
+ return map;
206
+ }
207
+ const BUNDLED_MODEL_COST_MAP = createBundledModelCostMap();
208
+ export function getBundledModelCostMap() {
209
+ return { ...BUNDLED_MODEL_COST_MAP };
210
+ }
104
211
  export function parseModelCostRates(value) {
105
212
  if (!isRecord(value))
106
213
  return undefined;
package/dist/usage.d.ts CHANGED
@@ -6,7 +6,7 @@ import type { CacheCoverageMetrics, CacheCoverageMode, CacheUsageBuckets, Cached
6
6
  * fields). This is distinct from the plugin *state* version managed by the
7
7
  * persistence layer; billing version only governs usage-cache staleness.
8
8
  */
9
- export declare const USAGE_BILLING_CACHE_VERSION = 7;
9
+ export declare const USAGE_BILLING_CACHE_VERSION = 8;
10
10
  export type ProviderUsage = {
11
11
  providerID: string;
12
12
  input: number;
package/dist/usage.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * fields). This is distinct from the plugin *state* version managed by the
5
5
  * persistence layer; billing version only governs usage-cache staleness.
6
6
  */
7
- export const USAGE_BILLING_CACHE_VERSION = 7;
7
+ export const USAGE_BILLING_CACHE_VERSION = 8;
8
8
  const MAX_RECENT_PROVIDER_EVENTS = 100;
9
9
  function emptyCacheUsageBucket() {
10
10
  return {
@@ -1,5 +1,5 @@
1
1
  import { TtlValueCache } from './cache.js';
2
- import { API_COST_ENABLED_PROVIDERS, cacheCoverageModeFromRates, calcEquivalentApiCostForMessage, canonicalApiCostProviderID, modelCostLookupKeys, modelCostKey, parseModelCostRates, } from './cost.js';
2
+ import { API_COST_ENABLED_PROVIDERS, cacheCoverageModeFromRates, calcEquivalentApiCostForMessage, canonicalApiCostProviderID, getBundledModelCostMap, modelCostLookupKeys, modelCostKey, parseModelCostRates, } from './cost.js';
3
3
  import { deleteSessionFromDayChunk, dateKeyFromTimestamp, scanAllSessions, updateSessionsInDayChunks, } from './storage.js';
4
4
  import { periodStart } from './period.js';
5
5
  import { debug, debugError, isRecord, mapConcurrent, swallow, } from './helpers.js';
@@ -36,9 +36,10 @@ export function createUsageService(deps) {
36
36
  const cached = modelCostCache.get();
37
37
  if (cached)
38
38
  return cached;
39
+ const fallbackMap = getBundledModelCostMap();
39
40
  const providerClient = deps.client;
40
41
  if (!providerClient.provider?.list) {
41
- return modelCostCache.set({}, 30_000);
42
+ return modelCostCache.set(fallbackMap, 30_000);
42
43
  }
43
44
  const response = await providerClient.provider
44
45
  .list({
@@ -83,7 +84,7 @@ export function createUsageService(deps) {
83
84
  }
84
85
  }
85
86
  return acc;
86
- }, {});
87
+ }, fallbackMap);
87
88
  return modelCostCache.set(map, Math.max(30_000, deps.config.quota.refreshMs));
88
89
  };
89
90
  const calcEquivalentApiCost = (message, modelCostMap) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leo000001/opencode-quota-sidebar",
3
- "version": "2.0.14",
3
+ "version": "2.0.15",
4
4
  "description": "OpenCode plugin that shows quota and token usage in session titles",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",