@almadar/llm 2.51.0 → 2.53.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.
@@ -1,169 +1,3 @@
1
- // src/rate-limiter.ts
2
- var RateLimiter = class {
3
- constructor(options = {}) {
4
- this.activeRequests = 0;
5
- this.queue = [];
6
- this.lastMinuteReset = Date.now();
7
- this.lastSecondReset = Date.now();
8
- this.pumping = false;
9
- this.currentBackoffMs = 0;
10
- this.wakeTimer = null;
11
- this.requestsPerMinute = options.requestsPerMinute ?? 60;
12
- this.requestsPerSecond = options.requestsPerSecond ?? 3;
13
- this.maxConcurrent = options.maxConcurrent ?? 5;
14
- this.baseBackoffMs = options.baseBackoffMs ?? 1e3;
15
- this.maxBackoffMs = options.maxBackoffMs ?? 6e4;
16
- this.minuteTokens = this.requestsPerMinute;
17
- this.secondTokens = this.requestsPerSecond;
18
- }
19
- async execute(fn, _maxRetries = 3) {
20
- return new Promise((resolve, reject) => {
21
- this.queue.push({
22
- execute: fn,
23
- resolve,
24
- reject,
25
- retryCount: 0
26
- });
27
- this.pump();
28
- });
29
- }
30
- getStatus() {
31
- return {
32
- queueLength: this.queue.length,
33
- activeRequests: this.activeRequests,
34
- minuteTokens: this.minuteTokens,
35
- secondTokens: this.secondTokens,
36
- backoffMs: this.currentBackoffMs
37
- };
38
- }
39
- reset() {
40
- this.minuteTokens = this.requestsPerMinute;
41
- this.secondTokens = this.requestsPerSecond;
42
- this.activeRequests = 0;
43
- this.queue = [];
44
- this.currentBackoffMs = 0;
45
- this.lastMinuteReset = Date.now();
46
- this.lastSecondReset = Date.now();
47
- if (this.wakeTimer !== null) {
48
- clearTimeout(this.wakeTimer);
49
- this.wakeTimer = null;
50
- }
51
- }
52
- /**
53
- * Start queued requests up to the rate/concurrency budget, then return —
54
- * in-flight requests re-enter the pump as they settle, and a wake timer
55
- * covers token-bucket refills and 429 backoff. Never awaits a request.
56
- */
57
- pump() {
58
- if (this.pumping) return;
59
- this.pumping = true;
60
- try {
61
- this.refillTokens();
62
- while (this.queue.length > 0 && this.currentBackoffMs === 0 && this.canMakeRequest()) {
63
- const request = this.queue.shift();
64
- if (!request) break;
65
- this.consumeTokens();
66
- this.activeRequests++;
67
- void this.settle(request);
68
- }
69
- } finally {
70
- this.pumping = false;
71
- }
72
- if (this.queue.length === 0) return;
73
- if (this.currentBackoffMs > 0) {
74
- this.scheduleWake(this.currentBackoffMs, true);
75
- } else if (this.activeRequests < this.maxConcurrent) {
76
- this.scheduleWake(this.getWaitTime(), false);
77
- }
78
- }
79
- scheduleWake(ms, clearsBackoff) {
80
- if (this.wakeTimer !== null) return;
81
- this.wakeTimer = setTimeout(() => {
82
- this.wakeTimer = null;
83
- if (clearsBackoff) this.currentBackoffMs = 0;
84
- this.pump();
85
- }, ms);
86
- }
87
- async settle(request) {
88
- try {
89
- const result = await request.execute();
90
- request.resolve(result);
91
- this.currentBackoffMs = 0;
92
- } catch (error) {
93
- const err = error instanceof Error ? error : new Error(String(error));
94
- if (this.isRateLimitError(err)) {
95
- this.currentBackoffMs = Math.min(
96
- this.baseBackoffMs * Math.pow(2, request.retryCount),
97
- this.maxBackoffMs
98
- );
99
- console.warn(
100
- `[RateLimiter] Rate limited. Backing off for ${this.currentBackoffMs}ms (retry ${request.retryCount + 1})`
101
- );
102
- if (request.retryCount < 3) {
103
- this.queue.unshift({
104
- ...request,
105
- retryCount: request.retryCount + 1
106
- });
107
- } else {
108
- request.reject(
109
- new Error(
110
- `Rate limit exceeded after ${request.retryCount + 1} retries: ${err.message}`
111
- )
112
- );
113
- }
114
- } else {
115
- request.reject(err);
116
- }
117
- } finally {
118
- this.activeRequests--;
119
- this.pump();
120
- }
121
- }
122
- refillTokens() {
123
- const now = Date.now();
124
- if (now - this.lastMinuteReset >= 6e4) {
125
- this.minuteTokens = this.requestsPerMinute;
126
- this.lastMinuteReset = now;
127
- }
128
- if (now - this.lastSecondReset >= 1e3) {
129
- this.secondTokens = this.requestsPerSecond;
130
- this.lastSecondReset = now;
131
- }
132
- }
133
- canMakeRequest() {
134
- return this.minuteTokens > 0 && this.secondTokens > 0 && this.activeRequests < this.maxConcurrent;
135
- }
136
- consumeTokens() {
137
- this.minuteTokens--;
138
- this.secondTokens--;
139
- }
140
- getWaitTime() {
141
- const now = Date.now();
142
- if (this.secondTokens <= 0) {
143
- return Math.max(0, 1e3 - (now - this.lastSecondReset));
144
- }
145
- if (this.minuteTokens <= 0) {
146
- return Math.max(0, 6e4 - (now - this.lastMinuteReset));
147
- }
148
- return 100;
149
- }
150
- isRateLimitError(error) {
151
- const message = error.message.toLowerCase();
152
- return message.includes("429") || message.includes("rate limit") || message.includes("too many requests") || message.includes("quota exceeded");
153
- }
154
- };
155
- var globalRateLimiter = null;
156
- function getGlobalRateLimiter(options) {
157
- if (!globalRateLimiter) {
158
- globalRateLimiter = new RateLimiter(options);
159
- }
160
- return globalRateLimiter;
161
- }
162
- function resetGlobalRateLimiter() {
163
- globalRateLimiter?.reset();
164
- globalRateLimiter = null;
165
- }
166
-
167
1
  // src/token-tracker.ts
168
2
  import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from "fs";
169
3
  import { dirname, join } from "path";
@@ -243,7 +77,7 @@ function refreshPricingCache() {
243
77
  }).catch(() => {
244
78
  });
245
79
  }
246
- function getCostForModel(model) {
80
+ function getCostForModelIfKnown(model) {
247
81
  const pricing = getPricing();
248
82
  const orId = MODEL_ID_MAP[model];
249
83
  if (orId && pricing[orId]) return pricing[orId];
@@ -251,7 +85,27 @@ function getCostForModel(model) {
251
85
  for (const [key, cost] of Object.entries(pricing)) {
252
86
  if (key.includes(model) || model.includes(key.split("/")[1] ?? "")) return cost;
253
87
  }
254
- return { promptCostPer1K: 0, completionCostPer1K: 0 };
88
+ return void 0;
89
+ }
90
+ function getCostForModel(model) {
91
+ return getCostForModelIfKnown(model) ?? { promptCostPer1K: 0, completionCostPer1K: 0 };
92
+ }
93
+ function priceTokens(costs, promptTokens, completionTokens, cached, written) {
94
+ const cacheReadRate = costs.cacheReadCostPer1K ?? costs.promptCostPer1K;
95
+ const cacheWriteRate = costs.cacheWriteCostPer1K ?? costs.promptCostPer1K;
96
+ const uncached = Math.max(0, promptTokens - cached - written);
97
+ return uncached / 1e3 * costs.promptCostPer1K + cached / 1e3 * cacheReadRate + written / 1e3 * cacheWriteRate + completionTokens / 1e3 * costs.completionCostPer1K;
98
+ }
99
+ function estimateCostUSD(model, tokens) {
100
+ const costs = getCostForModelIfKnown(model);
101
+ if (costs === void 0) return void 0;
102
+ return priceTokens(
103
+ costs,
104
+ tokens.promptTokens,
105
+ tokens.completionTokens,
106
+ Math.max(0, tokens.cachedPromptTokens ?? 0),
107
+ Math.max(0, tokens.cacheWriteTokens ?? 0)
108
+ );
255
109
  }
256
110
  var TokenTracker = class {
257
111
  constructor(model = "claude-sonnet-4-5-20250929") {
@@ -278,11 +132,7 @@ var TokenTracker = class {
278
132
  }
279
133
  /** Cache-aware cost for one (or an aggregate of) call(s), in USD. */
280
134
  costFor(model, promptTokens, completionTokens, cached, written) {
281
- const costs = getCostForModel(model);
282
- const cacheReadRate = costs.cacheReadCostPer1K ?? costs.promptCostPer1K;
283
- const cacheWriteRate = costs.cacheWriteCostPer1K ?? costs.promptCostPer1K;
284
- const uncached = Math.max(0, promptTokens - cached - written);
285
- return uncached / 1e3 * costs.promptCostPer1K + cached / 1e3 * cacheReadRate + written / 1e3 * cacheWriteRate + completionTokens / 1e3 * costs.completionCostPer1K;
135
+ return priceTokens(getCostForModel(model), promptTokens, completionTokens, cached, written);
286
136
  }
287
137
  /**
288
138
  * Record one LLM call's usage. `promptTokens` is the TOTAL input count
@@ -401,11 +251,9 @@ function resetGlobalTokenTracker() {
401
251
  }
402
252
 
403
253
  export {
404
- RateLimiter,
405
- getGlobalRateLimiter,
406
- resetGlobalRateLimiter,
254
+ estimateCostUSD,
407
255
  TokenTracker,
408
256
  getGlobalTokenTracker,
409
257
  resetGlobalTokenTracker
410
258
  };
411
- //# sourceMappingURL=chunk-RPG3SUIB.js.map
259
+ //# sourceMappingURL=chunk-T6AKOBX3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/token-tracker.ts"],"sourcesContent":["/**\n * Token Tracker for LLM Usage\n *\n * Tracks token usage across multiple LLM calls for:\n * - Cost estimation (pricing fetched from OpenRouter models API)\n * - Usage monitoring\n * - Quota management\n * - Per-call JSONL logging\n *\n * @packageDocumentation\n */\n\nimport { appendFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n callCount: number;\n /** Subset of `promptTokens` that were cache reads (billed at the cache-read rate). */\n cachedPromptTokens: number;\n /** Subset of `promptTokens` written to cache (Anthropic; billed at the cache-write rate). */\n cacheWriteTokens: number;\n}\n\nexport interface TokenCost {\n promptCostPer1K: number;\n completionCostPer1K: number;\n /** Per-1K rate for cache-read (cache-hit) prompt tokens. Falls back to prompt rate when absent. */\n cacheReadCostPer1K?: number;\n /** Per-1K rate for cache-write (cache-creation) prompt tokens. Falls back to prompt rate when absent. */\n cacheWriteCostPer1K?: number;\n}\n\nexport interface CallLogEntry {\n timestamp: string;\n provider: string;\n model: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Cache-read (cache-hit) subset of promptTokens, billed at the discounted rate. */\n cachedPromptTokens?: number;\n /** Cache-write subset of promptTokens (Anthropic). */\n cacheWriteTokens?: number;\n estimatedCost: number;\n durationMs?: number;\n source: 'local-log';\n}\n\n// ---------------------------------------------------------------------------\n// Pricing: fetched from OpenRouter /api/v1/models, cached to disk for 24h\n// ---------------------------------------------------------------------------\n\nconst ALMADAR_ROOT = process.env['ALMADAR_ROOT'] ?? process.cwd();\nconst PRICING_CACHE_PATH = join(ALMADAR_ROOT, '.llm-pricing-cache.json');\nconst CALL_LOG_PATH = join(ALMADAR_ROOT, '.llm-call-log.jsonl');\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours\n// Bump when the cached TokenCost shape changes so stale on-disk caches are\n// invalidated on upgrade. v2 added cacheReadCostPer1K / cacheWriteCostPer1K.\nconst PRICING_CACHE_VERSION = 2;\n\n/** Map from our local model name to OpenRouter model ID */\nconst MODEL_ID_MAP: Record<string, string> = {\n // Anthropic\n 'claude-opus-4-5-20250929': 'anthropic/claude-opus-4.5',\n 'claude-sonnet-4-5-20250929': 'anthropic/claude-sonnet-4.5',\n 'claude-sonnet-4-20250514': 'anthropic/claude-sonnet-4',\n 'claude-3-5-haiku-20241022': 'anthropic/claude-3.5-haiku',\n // DeepSeek — map to current versions on OpenRouter\n 'deepseek-chat': 'deepseek/deepseek-v4-flash',\n 'deepseek-coder': 'deepseek/deepseek-v4-flash',\n 'deepseek-reasoner': 'deepseek/deepseek-v4-flash',\n 'deepseek-v4-pro': 'deepseek/deepseek-v4-pro',\n 'deepseek-v4-flash': 'deepseek/deepseek-v4-flash',\n // Kimi\n 'kimi-k2.5': 'moonshotai/kimi-k2.5',\n};\n\n// Fallback: zero cost — forces OpenRouter fetch for real pricing\nconst FALLBACK_COSTS: Record<string, TokenCost> = {};\n\ninterface PricingCache {\n version?: number;\n fetchedAt: number;\n models: Record<string, TokenCost>;\n}\n\nlet pricingCache: PricingCache | null = null;\n\nfunction loadCachedPricing(): PricingCache | null {\n try {\n const raw = readFileSync(PRICING_CACHE_PATH, 'utf-8');\n const parsed = JSON.parse(raw) as PricingCache;\n if (parsed.version === PRICING_CACHE_VERSION && Date.now() - parsed.fetchedAt < CACHE_TTL_MS) {\n return parsed;\n }\n } catch {\n // No cache or expired\n }\n return null;\n}\n\nasync function fetchPricingFromOpenRouter(): Promise<Record<string, TokenCost>> {\n const res = await fetch('https://openrouter.ai/api/v1/models');\n if (!res.ok) throw new Error(`OpenRouter models API: HTTP ${res.status}`);\n const json = await res.json() as {\n data?: Array<{\n id: string;\n pricing?: {\n prompt?: string;\n completion?: string;\n input_cache_read?: string;\n input_cache_write?: string;\n };\n }>;\n };\n const models: Record<string, TokenCost> = {};\n for (const m of json.data ?? []) {\n const promptPerToken = parseFloat(m.pricing?.prompt ?? '0');\n const completionPerToken = parseFloat(m.pricing?.completion ?? '0');\n const cacheReadPerToken = parseFloat(m.pricing?.input_cache_read ?? '0');\n const cacheWritePerToken = parseFloat(m.pricing?.input_cache_write ?? '0');\n if (promptPerToken > 0 || completionPerToken > 0) {\n models[m.id] = {\n promptCostPer1K: promptPerToken * 1000,\n completionCostPer1K: completionPerToken * 1000,\n // 0 (field absent) → leave undefined so cost math falls back to the prompt rate.\n ...(cacheReadPerToken > 0 ? { cacheReadCostPer1K: cacheReadPerToken * 1000 } : {}),\n ...(cacheWritePerToken > 0 ? { cacheWriteCostPer1K: cacheWritePerToken * 1000 } : {}),\n };\n }\n }\n return models;\n}\n\n/**\n * Get pricing for all models. Uses 24h disk cache, fetches from OpenRouter on miss.\n * Non-blocking: returns cached/fallback immediately, refreshes in background if stale.\n */\nfunction getPricing(): Record<string, TokenCost> {\n if (pricingCache) return pricingCache.models;\n\n const diskCache = loadCachedPricing();\n if (diskCache) {\n pricingCache = diskCache;\n return diskCache.models;\n }\n\n // Trigger background fetch, return fallback for now\n refreshPricingCache();\n return FALLBACK_COSTS;\n}\n\nfunction refreshPricingCache(): void {\n fetchPricingFromOpenRouter()\n .then((models) => {\n pricingCache = { version: PRICING_CACHE_VERSION, fetchedAt: Date.now(), models };\n try {\n mkdirSync(dirname(PRICING_CACHE_PATH), { recursive: true });\n writeFileSync(PRICING_CACHE_PATH, JSON.stringify(pricingCache));\n } catch {\n // Non-critical\n }\n })\n .catch(() => {\n // Silently fail, use fallback\n });\n}\n\n/**\n * Look up a model's pricing row without a zero-cost fallback — `undefined`\n * means \"no pricing known yet\" (OpenRouter fetch pending, or the model\n * isn't listed), distinct from a model that is genuinely free. Single\n * lookup path: `getCostForModel` (zero-fallback, for the tracker's own\n * running totals) and `estimateCostUSD` (pure, callers outside the\n * tracker) both resolve through this.\n */\nfunction getCostForModelIfKnown(model: string): TokenCost | undefined {\n const pricing = getPricing();\n // Try direct match on OpenRouter ID\n const orId = MODEL_ID_MAP[model];\n if (orId && pricing[orId]) return pricing[orId];\n // Try direct key match (e.g., user passed \"openai/gpt-4o\")\n if (pricing[model]) return pricing[model];\n // Fuzzy: find first key containing the model name\n for (const [key, cost] of Object.entries(pricing)) {\n if (key.includes(model) || model.includes(key.split('/')[1] ?? '')) return cost;\n }\n return undefined;\n}\n\nfunction getCostForModel(model: string): TokenCost {\n // No pricing available — return zero (OpenRouter fetch pending or model not listed)\n return getCostForModelIfKnown(model) ?? { promptCostPer1K: 0, completionCostPer1K: 0 };\n}\n\n/** Cache-aware cost formula shared by `TokenTracker.costFor` (instance,\n * zero-fallback pricing) and `estimateCostUSD` (pure, `undefined` pricing\n * propagates to the caller instead of silently pricing at $0). */\nfunction priceTokens(\n costs: TokenCost,\n promptTokens: number,\n completionTokens: number,\n cached: number,\n written: number,\n): number {\n const cacheReadRate = costs.cacheReadCostPer1K ?? costs.promptCostPer1K;\n const cacheWriteRate = costs.cacheWriteCostPer1K ?? costs.promptCostPer1K;\n const uncached = Math.max(0, promptTokens - cached - written);\n return (\n (uncached / 1000) * costs.promptCostPer1K +\n (cached / 1000) * cacheReadRate +\n (written / 1000) * cacheWriteRate +\n (completionTokens / 1000) * costs.completionCostPer1K\n );\n}\n\nexport interface EstimateCostTokens {\n promptTokens: number;\n completionTokens: number;\n /** Subset of `promptTokens` served from the provider's prefix cache. */\n cachedPromptTokens?: number;\n /** Subset of `promptTokens` written to cache (Anthropic cache-write). */\n cacheWriteTokens?: number;\n}\n\n/**\n * Pure per-call cost estimate from token counts alone, priced from the SAME\n * OpenRouter-fetched table `TokenTracker` uses for the whole-run total (the\n * 24h disk cache in `getPricing` — no second pricing source). Callers with\n * tokens + a model name but no `TokenTracker` instance (e.g. a trace-event\n * emitter) use this instead of reimplementing the cache-aware math.\n *\n * Returns `undefined` when the model has no known pricing row — the\n * caller's job to render that as \"unknown\", never as `$0`.\n */\nexport function estimateCostUSD(model: string, tokens: EstimateCostTokens): number | undefined {\n const costs = getCostForModelIfKnown(model);\n if (costs === undefined) return undefined;\n return priceTokens(\n costs,\n tokens.promptTokens,\n tokens.completionTokens,\n Math.max(0, tokens.cachedPromptTokens ?? 0),\n Math.max(0, tokens.cacheWriteTokens ?? 0),\n );\n}\n\n// ---------------------------------------------------------------------------\n// TokenTracker\n// ---------------------------------------------------------------------------\n\nexport class TokenTracker {\n private model: string;\n private usage: TokenUsage = {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n callCount: 0,\n cachedPromptTokens: 0,\n cacheWriteTokens: 0,\n };\n\n /** Sum of provider-reported authoritative costs (e.g. OpenRouter `usage.cost`). */\n private authoritativeCostUSD = 0;\n /** Token buckets for calls WITHOUT an authoritative cost — priced cache-aware.\n * Keyed by the model that MADE the calls: `setModel` flips the tracker\n * between models mid-process (coordinator on pro, subagents on flash), and\n * pricing the aggregate at whichever model is current when someone reads\n * the estimate mispriced the whole history by up to the models' rate ratio\n * (snapshot/diff consumers saw phantom multi-dollar deltas — or $0 after a\n * negative-clamp — per battery spec). Per-model buckets keep the\n * retroactive late-pricing property without cross-model contamination. */\n private computedByModel = new Map<\n string,\n { promptTokens: number; completionTokens: number; cachedPromptTokens: number; cacheWriteTokens: number }\n >();\n\n constructor(model: string = 'claude-sonnet-4-5-20250929') {\n this.model = model;\n }\n\n /** Cache-aware cost for one (or an aggregate of) call(s), in USD. */\n private costFor(model: string, promptTokens: number, completionTokens: number, cached: number, written: number): number {\n return priceTokens(getCostForModel(model), promptTokens, completionTokens, cached, written);\n }\n\n /**\n * Record one LLM call's usage. `promptTokens` is the TOTAL input count\n * (cache reads + cache writes + uncached); `cachedPromptTokens` and\n * `cacheWriteTokens` are subsets of it, priced at their own (cheaper /\n * pricier) rates. Providers that don't report cache detail pass 0, which\n * reduces to the previous flat-rate behaviour.\n */\n addUsage(\n promptTokens: number,\n completionTokens: number,\n options?: {\n provider?: string;\n durationMs?: number;\n cachedPromptTokens?: number;\n cacheWriteTokens?: number;\n /** Provider-reported authoritative cost (e.g. OpenRouter `usage.cost`). When set, used verbatim. */\n costUSD?: number;\n },\n ): void {\n const cached = Math.min(promptTokens, Math.max(0, options?.cachedPromptTokens ?? 0));\n const written = Math.min(promptTokens - cached, Math.max(0, options?.cacheWriteTokens ?? 0));\n\n this.usage.promptTokens += promptTokens;\n this.usage.completionTokens += completionTokens;\n this.usage.totalTokens += promptTokens + completionTokens;\n this.usage.cachedPromptTokens += cached;\n this.usage.cacheWriteTokens += written;\n this.usage.callCount++;\n\n // Prefer the provider's authoritative cost (already cache- and routing-\n // adjusted). Otherwise bucket the tokens and price them cache-aware so\n // late-arriving pricing still applies retroactively to the estimate.\n const authoritative = options?.costUSD;\n let estimatedCost: number;\n if (authoritative != null && Number.isFinite(authoritative)) {\n this.authoritativeCostUSD += authoritative;\n estimatedCost = authoritative;\n } else {\n const bucket = this.computedByModel.get(this.model) ?? {\n promptTokens: 0,\n completionTokens: 0,\n cachedPromptTokens: 0,\n cacheWriteTokens: 0,\n };\n bucket.promptTokens += promptTokens;\n bucket.completionTokens += completionTokens;\n bucket.cachedPromptTokens += cached;\n bucket.cacheWriteTokens += written;\n this.computedByModel.set(this.model, bucket);\n estimatedCost = this.costFor(this.model, promptTokens, completionTokens, cached, written);\n }\n\n const entry: CallLogEntry = {\n timestamp: new Date().toISOString(),\n provider: options?.provider ?? 'unknown',\n model: this.model,\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n cachedPromptTokens: cached,\n cacheWriteTokens: written,\n estimatedCost,\n durationMs: options?.durationMs,\n source: 'local-log',\n };\n\n try {\n mkdirSync(dirname(CALL_LOG_PATH), { recursive: true });\n appendFileSync(CALL_LOG_PATH, JSON.stringify(entry) + '\\n');\n } catch {\n // Non-critical: don't break LLM calls if logging fails\n }\n }\n\n getSummary(): TokenUsage {\n return { ...this.usage };\n }\n\n getEstimatedCost(): number {\n let computed = 0;\n for (const [model, b] of this.computedByModel) {\n computed += this.costFor(\n model,\n b.promptTokens,\n b.completionTokens,\n b.cachedPromptTokens,\n b.cacheWriteTokens,\n );\n }\n return this.authoritativeCostUSD + computed;\n }\n\n getFormattedCost(): string {\n const cost = this.getEstimatedCost();\n return `$${cost.toFixed(4)}`;\n }\n\n getReport(): string {\n const summary = this.getSummary();\n const cost = this.getEstimatedCost();\n return [\n `Token Usage Report (${this.model})`,\n `─────────────────────────────`,\n `Calls: ${summary.callCount}`,\n `Prompt Tokens: ${summary.promptTokens.toLocaleString()}`,\n `Completion Tokens: ${summary.completionTokens.toLocaleString()}`,\n `Total Tokens: ${summary.totalTokens.toLocaleString()}`,\n `Estimated Cost: $${cost.toFixed(4)}`,\n ].join('\\n');\n }\n\n reset(): void {\n this.usage = {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n callCount: 0,\n cachedPromptTokens: 0,\n cacheWriteTokens: 0,\n };\n this.authoritativeCostUSD = 0;\n this.computedByModel.clear();\n }\n\n setModel(model: string): void {\n this.model = model;\n }\n}\n\n// Global tracker instance\nlet globalTracker: TokenTracker | null = null;\n\nexport function getGlobalTokenTracker(model?: string): TokenTracker {\n if (!globalTracker) {\n globalTracker = new TokenTracker(model);\n } else if (model) {\n globalTracker.setModel(model);\n }\n return globalTracker;\n}\n\nexport function resetGlobalTokenTracker(): void {\n globalTracker?.reset();\n}\n\nexport function getCallLogPath(): string {\n return CALL_LOG_PATH;\n}\n\n/** Force-refresh the pricing cache from OpenRouter. */\nexport async function refreshPricing(): Promise<void> {\n const models = await fetchPricingFromOpenRouter();\n pricingCache = { version: PRICING_CACHE_VERSION, fetchedAt: Date.now(), models };\n mkdirSync(dirname(PRICING_CACHE_PATH), { recursive: true });\n writeFileSync(PRICING_CACHE_PATH, JSON.stringify(pricingCache));\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { R as RateLimiterOptions, T as TokenUsage } from './rate-limiter-CXaf8aAy.js';
1
+ import { R as RateLimiterOptions, T as TokenUsage } from './rate-limiter-Bz0iSJgZ.js';
2
2
  import { ChatOpenAI } from '@langchain/openai';
3
3
  import { ChatAnthropic } from '@langchain/anthropic';
4
4
  import Anthropic from '@anthropic-ai/sdk';
@@ -133,6 +133,15 @@ interface LLMUsage {
133
133
  * `prompt_tokens_details.cached_tokens`, deepseek-native
134
134
  * `prompt_cache_hit_tokens`). Absent when the provider reports neither. */
135
135
  cachedPromptTokens?: number;
136
+ /**
137
+ * USD cost of this one call. OpenRouter's authoritative `usage.cost`
138
+ * (real, routing+cache-adjusted charge) when the provider is
139
+ * `openrouter`; otherwise `estimateCostUSD` priced from the same
140
+ * OpenRouter-fetched table `TokenTracker` uses for the whole-run total.
141
+ * Absent — never `0` — when neither is available (pricing fetch
142
+ * pending, or the model isn't in OpenRouter's catalog).
143
+ */
144
+ costUSD?: number;
136
145
  }
137
146
  type LLMFinishReason = 'stop' | 'length' | 'content_filter' | 'tool_calls' | null;
138
147
  interface LLMResponse<T> {
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import './rate-limiter-CXaf8aAy.js';
1
+ import './rate-limiter-Bz0iSJgZ.js';
2
2
  import '@langchain/openai';
3
3
  import '@langchain/anthropic';
4
4
  import '@anthropic-ai/sdk';
5
5
  import 'zod';
6
- export { A as ANTHROPIC_MODELS, C as CacheAwareLLMCallOptions, b as CacheableBlock, D as DEEPSEEK_MODELS, K as KIMI_MODELS, j as LLMCallOptions, a as LLMClient, k as LLMClientOptions, L as LLMFinishReason, l as LLMProvider, m as LLMResponse, n as LLMStreamChunk, o as LLMStreamOptions, p as LLMUsage, O as OPENAI_MODELS, q as OPENROUTER_MODELS, P as PROVIDER_CATALOG, r as ProviderCatalogEntry, s as ProviderConfig, V as VisionCallOptions, t as VisionImageMediaType, u as VisionImagePart, v as buildVisionMessageContent, w as createAnthropicClient, x as createCreativeClient, y as createDeepSeekClient, z as createFixClient, B as createKimiClient, E as createOpenAIClient, F as createOpenRouterClient, G as createRequirementsClient, H as createZhipuClient, I as getAvailableProvider, J as getSharedLLMClient, M as isProviderAvailable, N as listLmstudioModels, Q as listSelectableProviders, S as resetSharedLLMClient } from './client-SYMpnw-w.js';
6
+ export { A as ANTHROPIC_MODELS, C as CacheAwareLLMCallOptions, b as CacheableBlock, D as DEEPSEEK_MODELS, K as KIMI_MODELS, j as LLMCallOptions, a as LLMClient, k as LLMClientOptions, L as LLMFinishReason, l as LLMProvider, m as LLMResponse, n as LLMStreamChunk, o as LLMStreamOptions, p as LLMUsage, O as OPENAI_MODELS, q as OPENROUTER_MODELS, P as PROVIDER_CATALOG, r as ProviderCatalogEntry, s as ProviderConfig, V as VisionCallOptions, t as VisionImageMediaType, u as VisionImagePart, v as buildVisionMessageContent, w as createAnthropicClient, x as createCreativeClient, y as createDeepSeekClient, z as createFixClient, B as createKimiClient, E as createOpenAIClient, F as createOpenRouterClient, G as createRequirementsClient, H as createZhipuClient, I as getAvailableProvider, J as getSharedLLMClient, M as isProviderAvailable, N as listLmstudioModels, Q as listSelectableProviders, S as resetSharedLLMClient } from './client-DfzMDgkm.js';
7
7
  import '@almadar/core';
package/dist/client.js CHANGED
@@ -22,9 +22,10 @@ import {
22
22
  listLmstudioModels,
23
23
  listSelectableProviders,
24
24
  resetSharedLLMClient
25
- } from "./chunk-RBT22YSX.js";
25
+ } from "./chunk-DLEZ7FGQ.js";
26
26
  import "./chunk-P4VCT25B.js";
27
- import "./chunk-RPG3SUIB.js";
27
+ import "./chunk-MOIECDMB.js";
28
+ import "./chunk-T6AKOBX3.js";
28
29
  export {
29
30
  ANTHROPIC_MODELS,
30
31
  DEEPSEEK_MODELS,
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { L as LLMFinishReason, a as LLMClient } from './client-SYMpnw-w.js';
2
- export { A as ANTHROPIC_MODELS, C as CacheAwareLLMCallOptions, b as CacheableBlock, c as ChatCompletionChoice, d as ChatCompletionMessage, e as ChatCompletionResponse, f as ChatCompletionRole, g as ChatCompletionToolCall, h as ChatCompletionToolDef, i as ChatCompletionUsage, D as DEEPSEEK_MODELS, K as KIMI_MODELS, j as LLMCallOptions, k as LLMClientOptions, l as LLMProvider, m as LLMResponse, n as LLMStreamChunk, o as LLMStreamOptions, p as LLMUsage, O as OPENAI_MODELS, q as OPENROUTER_MODELS, P as PROVIDER_CATALOG, r as ProviderCatalogEntry, s as ProviderConfig, V as VisionCallOptions, t as VisionImageMediaType, u as VisionImagePart, v as buildVisionMessageContent, w as createAnthropicClient, x as createCreativeClient, y as createDeepSeekClient, z as createFixClient, B as createKimiClient, E as createOpenAIClient, F as createOpenRouterClient, G as createRequirementsClient, H as createZhipuClient, I as getAvailableProvider, J as getSharedLLMClient, M as isProviderAvailable, N as listLmstudioModels, Q as listSelectableProviders, R as parseChatCompletionResponse, S as resetSharedLLMClient } from './client-SYMpnw-w.js';
3
- export { a as RateLimiter, R as RateLimiterOptions, b as TokenTracker, T as TokenUsage, g as getGlobalRateLimiter, c as getGlobalTokenTracker, r as resetGlobalRateLimiter, d as resetGlobalTokenTracker } from './rate-limiter-CXaf8aAy.js';
1
+ import { L as LLMFinishReason, a as LLMClient } from './client-DfzMDgkm.js';
2
+ export { A as ANTHROPIC_MODELS, C as CacheAwareLLMCallOptions, b as CacheableBlock, c as ChatCompletionChoice, d as ChatCompletionMessage, e as ChatCompletionResponse, f as ChatCompletionRole, g as ChatCompletionToolCall, h as ChatCompletionToolDef, i as ChatCompletionUsage, D as DEEPSEEK_MODELS, K as KIMI_MODELS, j as LLMCallOptions, k as LLMClientOptions, l as LLMProvider, m as LLMResponse, n as LLMStreamChunk, o as LLMStreamOptions, p as LLMUsage, O as OPENAI_MODELS, q as OPENROUTER_MODELS, P as PROVIDER_CATALOG, r as ProviderCatalogEntry, s as ProviderConfig, V as VisionCallOptions, t as VisionImageMediaType, u as VisionImagePart, v as buildVisionMessageContent, w as createAnthropicClient, x as createCreativeClient, y as createDeepSeekClient, z as createFixClient, B as createKimiClient, E as createOpenAIClient, F as createOpenRouterClient, G as createRequirementsClient, H as createZhipuClient, I as getAvailableProvider, J as getSharedLLMClient, M as isProviderAvailable, N as listLmstudioModels, Q as listSelectableProviders, R as parseChatCompletionResponse, S as resetSharedLLMClient } from './client-DfzMDgkm.js';
3
+ export { E as EstimateCostTokens, a as RateLimiter, R as RateLimiterOptions, b as TokenTracker, T as TokenUsage, e as estimateCostUSD, g as getGlobalRateLimiter, c as getGlobalTokenTracker, r as resetGlobalRateLimiter, d as resetGlobalTokenTracker } from './rate-limiter-Bz0iSJgZ.js';
4
4
  import { JsonValue, ServiceParams, ServiceContract } from '@almadar/core';
5
5
  export { autoCloseJson, extractJsonFromText, isValidJson, parseJsonResponse, safeParseJson } from './json-parser.js';
6
6
  import { z } from 'zod';
7
7
  export { JsonSchema, STRUCTURED_OUTPUT_MODELS, StructuredGenerationOptions, StructuredGenerationResult, StructuredOutputClient, StructuredOutputOptions, getStructuredOutputClient, isStructuredOutputAvailable, resetStructuredOutputClient } from './structured-output.js';
8
- export { ErrorPrediction, GFlowNetResult, GoalSpec, MasarError, MasarGenerateOptions, MasarGenerateResult, MasarHealthResult, MasarProvider, MasarProviderOptions, PredictErrorsResult, RankEditsResult, RankedEdit, getMasarProvider, resetMasarProvider } from './providers/index.js';
8
+ export { ErrorPrediction, GFlowNetResult, GoalSpec, JEV_DECISIONS_URL, JEV_MODELS, JevAnswer, JevChoiceAnswer, JevChoiceQuestion, JevDecideRequest, JevDecideResult, JevError, JevHealthResult, JevJsonValue, JevModelId, JevNoulAnswer, JevNoulQuestion, JevProvider, JevProviderOptions, JevQuestion, JevScoreAnswer, JevScoreQuestion, JevState, JevUsage, MasarError, MasarGenerateOptions, MasarGenerateResult, MasarHealthResult, MasarProvider, MasarProviderOptions, PredictErrorsResult, RankEditsResult, RankedEdit, getJevProvider, getMasarProvider, isJevAvailable, resetJevProvider, resetMasarProvider } from './providers/index.js';
9
9
  import '@langchain/openai';
10
10
  import '@langchain/anthropic';
11
11
  import '@anthropic-ai/sdk';
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  listSelectableProviders,
24
24
  parseChatCompletionResponse,
25
25
  resetSharedLLMClient
26
- } from "./chunk-RBT22YSX.js";
26
+ } from "./chunk-DLEZ7FGQ.js";
27
27
  import {
28
28
  autoCloseJson,
29
29
  extractJsonFromText,
@@ -37,21 +37,31 @@ import {
37
37
  getStructuredOutputClient,
38
38
  isStructuredOutputAvailable,
39
39
  resetStructuredOutputClient
40
- } from "./chunk-5AM54OAM.js";
40
+ } from "./chunk-SJE3GTGZ.js";
41
41
  import {
42
42
  RateLimiter,
43
- TokenTracker,
44
43
  getGlobalRateLimiter,
45
- getGlobalTokenTracker,
46
- resetGlobalRateLimiter,
47
- resetGlobalTokenTracker
48
- } from "./chunk-RPG3SUIB.js";
44
+ resetGlobalRateLimiter
45
+ } from "./chunk-MOIECDMB.js";
49
46
  import {
47
+ JEV_DECISIONS_URL,
48
+ JEV_MODELS,
49
+ JevError,
50
+ JevProvider,
50
51
  MasarError,
51
52
  MasarProvider,
53
+ getJevProvider,
52
54
  getMasarProvider,
55
+ isJevAvailable,
56
+ resetJevProvider,
53
57
  resetMasarProvider
54
- } from "./chunk-MUTXGY6D.js";
58
+ } from "./chunk-OXFWONZP.js";
59
+ import {
60
+ TokenTracker,
61
+ estimateCostUSD,
62
+ getGlobalTokenTracker,
63
+ resetGlobalTokenTracker
64
+ } from "./chunk-T6AKOBX3.js";
55
65
 
56
66
  // src/embedding-client.ts
57
67
  var EMBEDDING_PROVIDERS = ["openai", "openrouter", "lmstudio"];
@@ -929,6 +939,10 @@ export {
929
939
  EmbeddingClient,
930
940
  IMAGE_PROVIDER_CATALOG,
931
941
  ImageClient,
942
+ JEV_DECISIONS_URL,
943
+ JEV_MODELS,
944
+ JevError,
945
+ JevProvider,
932
946
  KIMI_MODELS,
933
947
  LLMClient,
934
948
  LOCAL_IMAGE_DEFAULTS,
@@ -959,14 +973,17 @@ export {
959
973
  createRequirementsClient,
960
974
  createZhipuClient,
961
975
  detectTruncation,
976
+ estimateCostUSD,
962
977
  extractJsonFromText,
963
978
  findLastCompleteElement,
964
979
  getAvailableProvider,
965
980
  getGlobalRateLimiter,
966
981
  getGlobalTokenTracker,
982
+ getJevProvider,
967
983
  getMasarProvider,
968
984
  getSharedLLMClient,
969
985
  getStructuredOutputClient,
986
+ isJevAvailable,
970
987
  isLikelyTruncated,
971
988
  isProviderAvailable,
972
989
  isStructuredOutputAvailable,
@@ -978,6 +995,7 @@ export {
978
995
  parseJsonResponse,
979
996
  resetGlobalRateLimiter,
980
997
  resetGlobalTokenTracker,
998
+ resetJevProvider,
981
999
  resetMasarProvider,
982
1000
  resetSharedLLMClient,
983
1001
  resetStructuredOutputClient,