@plumbus/ai-bedrock 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.
@@ -0,0 +1,103 @@
1
+ import type { BedrockModelRate } from './types.js';
2
+ export interface PricingStoreOptions {
3
+ region: string;
4
+ pricingFilePath?: string;
5
+ pricingCacheTtlMs?: number;
6
+ pricingRefreshTimeoutMs?: number;
7
+ /** Injected for tests. */
8
+ fetchImpl?: typeof fetch;
9
+ }
10
+ export interface BedrockPricingStore {
11
+ /** Ensure rates are loaded (file or network). Safe to call repeatedly. */
12
+ warm: () => Promise<void>;
13
+ getRate: (modelId: string) => BedrockModelRate | null;
14
+ listRates: () => Array<{
15
+ id: string;
16
+ rate: BedrockModelRate;
17
+ }>;
18
+ /**
19
+ * USD for a usage record, or `undefined` when no rate is known for the model.
20
+ *
21
+ * `undefined` (not `0`) is deliberate: core prefers an adapter-supplied `cost`
22
+ * over its own catalog with `providerCost ?? calculateModelCost(...)`, so a
23
+ * `0` for an unpriced model would silently record real spend as free in the
24
+ * ledger and against daily cost limits.
25
+ */
26
+ calculateCost: (modelId: string, usage: {
27
+ inputTokens: number;
28
+ outputTokens: number;
29
+ cachedInputTokens?: number;
30
+ cacheWriteTokens?: number;
31
+ }) => number | undefined;
32
+ }
33
+ /**
34
+ * Normalize a Bedrock model id to a family key for rate lookup.
35
+ * Examples:
36
+ * - `us.anthropic.claude-haiku-4-5-20251001-v1:0` → `anthropic.claude-haiku-4-5`
37
+ * - `amazon.titan-embed-text-v2:0` → `amazon.titan-embed-text-v2`
38
+ */
39
+ export declare function normalizeBedrockModelId(modelId: string): string;
40
+ /**
41
+ * Prefer SDK-shaped ids already present in offer attributes / usagetype.
42
+ * Returns a normalized family key, or null.
43
+ *
44
+ * Recognition is structural (`provider.model…`) — not an allowlist of vendors.
45
+ */
46
+ export declare function extractModelIdFromOfferAttrs(attrs: {
47
+ model?: string;
48
+ modelId?: string;
49
+ servicename?: string;
50
+ usagetype?: string;
51
+ }): string | null;
52
+ /**
53
+ * Last-resort generative inference from marketplace display names.
54
+ * Not a hardcoded catalog of every AWS model — only a few stable name shapes
55
+ * (Claude tier+version, Titan embed). Prefer pricing files or extracted ids.
56
+ */
57
+ export declare function inferFamilyFromDisplayName(name: string): {
58
+ family: string;
59
+ kind: BedrockModelRate['kind'];
60
+ } | null;
61
+ interface OfferProductAttrs {
62
+ model?: string;
63
+ modelId?: string;
64
+ /** First-party Titan rows carry the model name here, not in `model`. */
65
+ titanModel?: string;
66
+ servicename?: string;
67
+ feature?: string;
68
+ inferenceType?: string;
69
+ usagetype?: string;
70
+ provider?: string;
71
+ service_tier?: string;
72
+ }
73
+ interface OfferPriceDimension {
74
+ unit?: string;
75
+ description?: string;
76
+ pricePerUnit?: {
77
+ USD?: string;
78
+ };
79
+ }
80
+ interface OfferTermDimension {
81
+ priceDimensions?: Record<string, OfferPriceDimension>;
82
+ }
83
+ interface OfferJson {
84
+ products: Record<string, {
85
+ attributes?: OfferProductAttrs;
86
+ }>;
87
+ terms?: {
88
+ OnDemand?: Record<string, Record<string, OfferTermDimension>>;
89
+ };
90
+ }
91
+ /**
92
+ * Parse AWS offer JSON(s) into family-keyed rates (regional on-demand only).
93
+ *
94
+ * Resolution order per product:
95
+ * 1. SDK-shaped id in `modelId` / `model` / embedded in `usagetype`
96
+ * 2. Generative inference from marketplace display names (Claude / Titan / Nova shapes)
97
+ * 3. Skip (unknown → no rate; use a pricing file in production)
98
+ */
99
+ export declare function parseAwsOfferRates(offers: OfferJson[]): Map<string, BedrockModelRate>;
100
+ export declare function parsePricingFile(raw: unknown): Map<string, BedrockModelRate>;
101
+ export declare function createPricingStore(options: PricingStoreOptions): BedrockPricingStore;
102
+ export {};
103
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,501 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
3
+ const DEFAULT_REFRESH_TIMEOUT_MS = 15_000;
4
+ /**
5
+ * Cooldown after a failed auto-download before the next attempt. Without this
6
+ * every request would re-pay the fetch timeout when the Price List CDN is
7
+ * unreachable (locked-down clusters), since a failed load leaves rates empty.
8
+ */
9
+ const FAILED_REFRESH_COOLDOWN_MS = 5 * 60 * 1000;
10
+ /**
11
+ * Structural shape of a Bedrock SDK model id: `provider.model…`
12
+ * (optional geo inference-profile prefix `us.` / `eu.` / …).
13
+ *
14
+ * No provider/model allowlist — anything matching this shape is treated as an
15
+ * id. Marketing display names (spaces, no `provider.model` form) do not match.
16
+ */
17
+ const SDK_MODEL_ID_SHAPE = /^(?:(?:us|eu|apac|ap|sa|ca|me|af|il|global)\.)?[a-z]{2,}\.[a-z0-9][a-z0-9._:-]*$/i;
18
+ /** Find the same shape inside a longer string (e.g. Price List usagetype). */
19
+ const SDK_MODEL_ID_IN_TEXT = /\b((?:(?:us|eu|apac|ap|sa|ca|me|af|il|global)\.)?[a-z]{2,}\.[a-z0-9][a-z0-9._-]*)/i;
20
+ /**
21
+ * Normalize a Bedrock model id to a family key for rate lookup.
22
+ * Examples:
23
+ * - `us.anthropic.claude-haiku-4-5-20251001-v1:0` → `anthropic.claude-haiku-4-5`
24
+ * - `amazon.titan-embed-text-v2:0` → `amazon.titan-embed-text-v2`
25
+ */
26
+ export function normalizeBedrockModelId(modelId) {
27
+ let id = modelId.trim();
28
+ id = id.replace(/^(us|eu|apac|ap|sa|ca|me|af|il|global)\./i, '');
29
+ // Dated inference ids: …-20251001-v1:0
30
+ id = id.replace(/-\d{8}-v\d+:\d+$/i, '');
31
+ // Trailing :0 / :1 only (keep model revision suffixes like -v2)
32
+ id = id.replace(/:\d+$/i, '');
33
+ return id;
34
+ }
35
+ function looksLikeSdkModelId(value) {
36
+ const v = value.trim();
37
+ if (!v || /\s/.test(v))
38
+ return false;
39
+ return SDK_MODEL_ID_SHAPE.test(v);
40
+ }
41
+ function stripPricingSuffixFromId(raw) {
42
+ let id = raw;
43
+ id = id.replace(/-(?:mantle-)?(?:input|output)[_-]tokens.*$/i, '');
44
+ id = id.replace(/-(?:Input|Output|Response)TokenCount.*$/i, '');
45
+ id = id.replace(/-(?:input|output)_tokens_.*$/i, '');
46
+ return id;
47
+ }
48
+ /**
49
+ * Prefer SDK-shaped ids already present in offer attributes / usagetype.
50
+ * Returns a normalized family key, or null.
51
+ *
52
+ * Recognition is structural (`provider.model…`) — not an allowlist of vendors.
53
+ */
54
+ export function extractModelIdFromOfferAttrs(attrs) {
55
+ for (const candidate of [attrs.modelId, attrs.model]) {
56
+ if (candidate && looksLikeSdkModelId(candidate)) {
57
+ return normalizeBedrockModelId(stripPricingSuffixFromId(candidate.trim()));
58
+ }
59
+ }
60
+ const usage = attrs.usagetype ?? '';
61
+ const embedded = usage.match(SDK_MODEL_ID_IN_TEXT);
62
+ if (embedded?.[1]) {
63
+ return normalizeBedrockModelId(stripPricingSuffixFromId(embedded[1]));
64
+ }
65
+ return null;
66
+ }
67
+ function inferKind(family) {
68
+ if (/embed/i.test(family))
69
+ return 'embedding';
70
+ return 'text';
71
+ }
72
+ /**
73
+ * Last-resort generative inference from marketplace display names.
74
+ * Not a hardcoded catalog of every AWS model — only a few stable name shapes
75
+ * (Claude tier+version, Titan embed). Prefer pricing files or extracted ids.
76
+ */
77
+ export function inferFamilyFromDisplayName(name) {
78
+ const n = name.trim();
79
+ if (!n)
80
+ return null;
81
+ // "Claude Haiku 4.5 (Amazon Bedrock Edition)" / "Claude Sonnet 4"
82
+ let m = n.match(/claude\s+(haiku|sonnet|opus)\s+(\d+(?:\.\d+)?)/i);
83
+ if (m?.[1] && m[2]) {
84
+ const tier = m[1].toLowerCase();
85
+ const ver = m[2].replace(/\./g, '-');
86
+ return { family: `anthropic.claude-${tier}-${ver}`, kind: 'text' };
87
+ }
88
+ // "Claude 3.5 Haiku" / "Claude 3 Sonnet"
89
+ m = n.match(/claude\s+(\d+(?:\.\d+)?)\s+(haiku|sonnet|opus)/i);
90
+ if (m?.[1] && m[2]) {
91
+ const ver = m[1].replace(/\./g, '-');
92
+ const tier = m[2].toLowerCase();
93
+ return { family: `anthropic.claude-${ver}-${tier}`, kind: 'text' };
94
+ }
95
+ // Titan embeddings. Offer rows spell these several ways and often only in the
96
+ // `titanModel` attribute: "Titan Text Embeddings V2", "Titan Embed Text V1",
97
+ // "TitanEmbeddingsV2-Text-input", "Titan Embeddings G1 Text".
98
+ if (/titan/i.test(n) && /embed/i.test(n)) {
99
+ const modality = /image|multimodal/i.test(n) ? 'image' : 'text';
100
+ // No \b before v — real rows run it together ("TitanEmbeddingsV2-Text-input").
101
+ const version = n.match(/v(\d+)/i)?.[1] ?? (/\bg1\b/i.test(n) ? '1' : null);
102
+ if (version) {
103
+ return { family: `amazon.titan-embed-${modality}-v${version}`, kind: 'embedding' };
104
+ }
105
+ }
106
+ // "Amazon Nova Lite" / "Nova Pro"
107
+ m = n.match(/\bnova\s+(micro|lite|pro|premier)\b/i);
108
+ if (m?.[1]) {
109
+ return { family: `amazon.nova-${m[1].toLowerCase()}`, kind: 'text' };
110
+ }
111
+ return null;
112
+ }
113
+ function resolveFamily(attrs) {
114
+ const extracted = extractModelIdFromOfferAttrs(attrs);
115
+ if (extracted) {
116
+ return { family: extracted, kind: inferKind(extracted) };
117
+ }
118
+ // `servicename` is the literal "Amazon Bedrock" on first-party rows, so the
119
+ // model name lives in `model` / `titanModel` there.
120
+ const display = attrs.model ?? attrs.titanModel ?? attrs.servicename ?? '';
121
+ return inferFamilyFromDisplayName(display);
122
+ }
123
+ /**
124
+ * Convert a Price List unit to USD per 1M tokens, or null when the unit is not
125
+ * a token unit at all.
126
+ *
127
+ * Returning null (rather than assuming per-MTok) matters: offer files also
128
+ * carry `hour`, `image`, `Model/month`, `Search Units`, `1M TPM Hour` and
129
+ * friends, and silently treating one of those as a token rate would be wrong
130
+ * by orders of magnitude in the ledger. A skipped row simply has no rate.
131
+ */
132
+ function toPerMTok(priceUsd, unit) {
133
+ const u = unit.toLowerCase().trim();
134
+ // "1M TPM Hour" is a provisioned-throughput unit, not a token price.
135
+ if (u.includes('tpm'))
136
+ return null;
137
+ if (!/token/.test(u))
138
+ return null;
139
+ if (u.includes('1m') || u.includes('million'))
140
+ return priceUsd;
141
+ if (u.includes('1k') || u.includes('thousand'))
142
+ return priceUsd * 1000;
143
+ if (u === 'tokens' || u === 'token')
144
+ return priceUsd * 1_000_000;
145
+ return null;
146
+ }
147
+ /**
148
+ * On-demand standard tier: excludes batch, provisioned/reserved,
149
+ * latency-optimized, priority and flex. Global and cache rows DO pass here —
150
+ * they are separated afterwards, since we price them explicitly.
151
+ */
152
+ function isStandardTier(attrs) {
153
+ const usage = attrs.usagetype ?? '';
154
+ if (/Batch|LatencyOptimized|Reserved|ProvisionedThroughput/i.test(usage))
155
+ return false;
156
+ if (/priority|flex/i.test(usage))
157
+ return false;
158
+ if (attrs.feature && !/on-demand/i.test(attrs.feature) && attrs.feature !== '')
159
+ return false;
160
+ if (attrs.service_tier && /priority|flex/i.test(attrs.service_tier))
161
+ return false;
162
+ return true;
163
+ }
164
+ /** Cross-region **global** inference profile SKU (billed below the regional rate). */
165
+ function isGlobalRow(attrs) {
166
+ return /Global|global[_-]standard/i.test(attrs.usagetype ?? '');
167
+ }
168
+ /**
169
+ * Prompt-cache SKU. `CacheWrite1h` is a longer-TTL tier billed above the
170
+ * default 5-minute write, so it is not folded into the standard cache rate.
171
+ */
172
+ function cacheRowKind(attrs) {
173
+ const usage = attrs.usagetype ?? '';
174
+ if (!/Cache/i.test(usage))
175
+ return null;
176
+ if (/CacheRead/i.test(usage))
177
+ return 'read';
178
+ if (/CacheWrite1h/i.test(usage))
179
+ return 'other';
180
+ if (/CacheWrite/i.test(usage))
181
+ return 'write';
182
+ return 'other';
183
+ }
184
+ /**
185
+ * Which side of the ledger a token row belongs to, independent of tier.
186
+ * Output is checked first so `…OutputTokenCount…` can never fall through to an
187
+ * input match.
188
+ */
189
+ function tokenDirection(attrs) {
190
+ const inf = attrs.inferenceType ?? '';
191
+ const usage = attrs.usagetype ?? '';
192
+ if (/output\s*tokens?/i.test(inf))
193
+ return 'output';
194
+ if (/input\s*tokens?/i.test(inf))
195
+ return 'input';
196
+ if (/OutputTokenCount|ResponseTokenCount/i.test(usage))
197
+ return 'output';
198
+ if (/InputTokenCount/i.test(usage))
199
+ return 'input';
200
+ if (/output[_-]tokens/i.test(usage))
201
+ return 'output';
202
+ if (/input[_-]tokens/i.test(usage))
203
+ return 'input';
204
+ return null;
205
+ }
206
+ function extractOnDemandPrice(offer, sku) {
207
+ const onDemand = offer.terms?.OnDemand?.[sku];
208
+ if (!onDemand)
209
+ return null;
210
+ for (const dim of Object.values(onDemand)) {
211
+ const dims = dim.priceDimensions;
212
+ if (!dims)
213
+ continue;
214
+ for (const pd of Object.values(dims)) {
215
+ const raw = pd.pricePerUnit?.USD;
216
+ if (raw == null)
217
+ continue;
218
+ const usd = Number.parseFloat(raw);
219
+ if (!Number.isFinite(usd))
220
+ continue;
221
+ return { usd, unit: pd.unit ?? '1M tokens' };
222
+ }
223
+ }
224
+ return null;
225
+ }
226
+ /**
227
+ * Parse AWS offer JSON(s) into family-keyed rates (regional on-demand only).
228
+ *
229
+ * Resolution order per product:
230
+ * 1. SDK-shaped id in `modelId` / `model` / embedded in `usagetype`
231
+ * 2. Generative inference from marketplace display names (Claude / Titan / Nova shapes)
232
+ * 3. Skip (unknown → no rate; use a pricing file in production)
233
+ */
234
+ export function parseAwsOfferRates(offers) {
235
+ const input = new Map();
236
+ const output = new Map();
237
+ const globalInput = new Map();
238
+ const globalOutput = new Map();
239
+ const cacheRead = new Map();
240
+ const cacheWrite = new Map();
241
+ /**
242
+ * Lowest wins. Offer files can carry several standard-tier SKUs for one
243
+ * family (context tiers, duplicated marketplace listings) and object key
244
+ * order is not a meaningful tie-break — "first one seen" made the rate depend
245
+ * on JSON ordering. The base tier is the conservative, reproducible choice.
246
+ */
247
+ function keepLowest(map, family, perMTok) {
248
+ const prev = map.get(family);
249
+ if (prev == null || perMTok < prev)
250
+ map.set(family, perMTok);
251
+ }
252
+ for (const offer of offers) {
253
+ for (const [sku, product] of Object.entries(offer.products ?? {})) {
254
+ const attrs = product.attributes ?? {};
255
+ if (!isStandardTier(attrs))
256
+ continue;
257
+ const mapped = resolveFamily(attrs);
258
+ if (!mapped)
259
+ continue;
260
+ const price = extractOnDemandPrice(offer, sku);
261
+ if (!price)
262
+ continue;
263
+ const perMTok = toPerMTok(price.usd, price.unit);
264
+ if (perMTok == null)
265
+ continue;
266
+ const cache = cacheRowKind(attrs);
267
+ if (cache) {
268
+ // Cache rates are regional-only here; a global cache SKU would need its
269
+ // own slot and no consumer asks for that yet.
270
+ if (isGlobalRow(attrs))
271
+ continue;
272
+ if (cache === 'read')
273
+ keepLowest(cacheRead, mapped.family, perMTok);
274
+ else if (cache === 'write')
275
+ keepLowest(cacheWrite, mapped.family, perMTok);
276
+ continue;
277
+ }
278
+ const direction = tokenDirection(attrs);
279
+ if (!direction)
280
+ continue;
281
+ if (isGlobalRow(attrs)) {
282
+ keepLowest(direction === 'input' ? globalInput : globalOutput, mapped.family, perMTok);
283
+ continue;
284
+ }
285
+ if (direction === 'input') {
286
+ const prev = input.get(mapped.family);
287
+ if (prev == null || perMTok < prev.perMTok) {
288
+ input.set(mapped.family, { perMTok, kind: mapped.kind });
289
+ }
290
+ }
291
+ else {
292
+ keepLowest(output, mapped.family, perMTok);
293
+ }
294
+ }
295
+ }
296
+ const rates = new Map();
297
+ for (const [family, inp] of input) {
298
+ const rate = {
299
+ inputPerMTok: inp.perMTok,
300
+ outputPerMTok: output.get(family) ?? 0,
301
+ kind: inp.kind,
302
+ };
303
+ const read = cacheRead.get(family);
304
+ const write = cacheWrite.get(family);
305
+ const gIn = globalInput.get(family);
306
+ const gOut = globalOutput.get(family);
307
+ if (read != null)
308
+ rate.cacheReadPerMTok = read;
309
+ if (write != null)
310
+ rate.cacheWritePerMTok = write;
311
+ if (gIn != null)
312
+ rate.globalInputPerMTok = gIn;
313
+ if (gOut != null)
314
+ rate.globalOutputPerMTok = gOut;
315
+ rates.set(family, rate);
316
+ }
317
+ return rates;
318
+ }
319
+ export function parsePricingFile(raw) {
320
+ if (raw == null || typeof raw !== 'object') {
321
+ throw new Error('Bedrock pricing file must be a JSON object');
322
+ }
323
+ const doc = raw;
324
+ if (doc.version !== 1) {
325
+ throw new Error(`Unsupported Bedrock pricing file version: ${String(doc.version)}`);
326
+ }
327
+ if (doc.models == null || typeof doc.models !== 'object') {
328
+ throw new Error('Bedrock pricing file must include a "models" object');
329
+ }
330
+ const rates = new Map();
331
+ for (const [id, rate] of Object.entries(doc.models)) {
332
+ if (rate == null || typeof rate !== 'object')
333
+ continue;
334
+ if (typeof rate.inputPerMTok !== 'number' || typeof rate.outputPerMTok !== 'number') {
335
+ throw new Error(`Invalid rate for model "${id}": inputPerMTok and outputPerMTok are required numbers`);
336
+ }
337
+ const parsedRate = {
338
+ inputPerMTok: rate.inputPerMTok,
339
+ outputPerMTok: rate.outputPerMTok,
340
+ kind: rate.kind,
341
+ };
342
+ // Optional refinements — omitted keys fall back to multipliers / regional.
343
+ if (typeof rate.cacheReadPerMTok === 'number') {
344
+ parsedRate.cacheReadPerMTok = rate.cacheReadPerMTok;
345
+ }
346
+ if (typeof rate.cacheWritePerMTok === 'number') {
347
+ parsedRate.cacheWritePerMTok = rate.cacheWritePerMTok;
348
+ }
349
+ if (typeof rate.globalInputPerMTok === 'number') {
350
+ parsedRate.globalInputPerMTok = rate.globalInputPerMTok;
351
+ }
352
+ if (typeof rate.globalOutputPerMTok === 'number') {
353
+ parsedRate.globalOutputPerMTok = rate.globalOutputPerMTok;
354
+ }
355
+ rates.set(id, parsedRate);
356
+ // Also index by normalized family so versioned ids resolve.
357
+ const family = normalizeBedrockModelId(id);
358
+ const copied = rates.get(id);
359
+ if (family !== id && copied != null && !rates.has(family)) {
360
+ rates.set(family, copied);
361
+ }
362
+ }
363
+ return rates;
364
+ }
365
+ async function fetchOfferJson(region, service, fetchImpl, timeoutMs) {
366
+ const url = `https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/${service}/current/${region}/index.json`;
367
+ try {
368
+ const resp = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
369
+ if (!resp.ok) {
370
+ console.warn(`[plumbus/ai-bedrock] Price List fetch ${service} returned ${resp.status}`);
371
+ return null;
372
+ }
373
+ return (await resp.json());
374
+ }
375
+ catch (err) {
376
+ const msg = err instanceof Error ? err.message : String(err);
377
+ console.warn(`[plumbus/ai-bedrock] Price List fetch ${service} failed (${msg})`);
378
+ return null;
379
+ }
380
+ }
381
+ export function createPricingStore(options) {
382
+ const ttlMs = options.pricingCacheTtlMs ?? DEFAULT_TTL_MS;
383
+ const refreshTimeoutMs = options.pricingRefreshTimeoutMs ?? DEFAULT_REFRESH_TIMEOUT_MS;
384
+ const fetchImpl = options.fetchImpl ?? fetch;
385
+ let rates = new Map();
386
+ let loadedAt = 0;
387
+ let failedAt = 0;
388
+ let warmPromise = null;
389
+ let backgroundRefresh = null;
390
+ function lookup(modelId) {
391
+ const exact = rates.get(modelId);
392
+ if (exact)
393
+ return exact;
394
+ const family = normalizeBedrockModelId(modelId);
395
+ const byFamily = rates.get(family);
396
+ if (byFamily)
397
+ return byFamily;
398
+ // Display-name inference yields version-less keys (`amazon.nova-lite`) while
399
+ // real ids normalize to versioned ones (`amazon.nova-lite-v1` from
400
+ // `amazon.nova-lite-v1:0`). Try the version-less form last so keys that are
401
+ // genuinely versioned (`amazon.titan-embed-text-v2`) still win above.
402
+ const versionless = family.replace(/-v\d+$/i, '');
403
+ if (versionless !== family) {
404
+ return rates.get(versionless) ?? null;
405
+ }
406
+ return null;
407
+ }
408
+ async function loadFromFile(path) {
409
+ const text = await readFile(path, 'utf8');
410
+ const json = JSON.parse(text);
411
+ rates = parsePricingFile(json);
412
+ loadedAt = Date.now();
413
+ }
414
+ async function loadFromNetwork() {
415
+ const [bedrock, foundation] = await Promise.all([
416
+ fetchOfferJson(options.region, 'AmazonBedrock', fetchImpl, refreshTimeoutMs),
417
+ fetchOfferJson(options.region, 'AmazonBedrockFoundationModels', fetchImpl, refreshTimeoutMs),
418
+ ]);
419
+ const offers = [bedrock, foundation].filter((o) => o != null);
420
+ if (offers.length === 0) {
421
+ failedAt = Date.now();
422
+ console.warn(`[plumbus/ai-bedrock] Could not download Price List for region ${options.region}; cost stays unknown until rates are available (retry in ${Math.round(FAILED_REFRESH_COOLDOWN_MS / 60_000)}m). Prefer AI_BEDROCK_PRICING_FILE in production.`);
423
+ return;
424
+ }
425
+ failedAt = 0;
426
+ rates = parseAwsOfferRates(offers);
427
+ loadedAt = Date.now();
428
+ if (rates.size === 0) {
429
+ console.warn(`[plumbus/ai-bedrock] Price List downloaded for ${options.region} but no regional on-demand rates could be keyed to Bedrock model ids. Mount AI_BEDROCK_PRICING_FILE with explicit family keys.`);
430
+ }
431
+ }
432
+ /** Refresh once in the background; callers keep serving the stale rates. */
433
+ function refreshInBackground() {
434
+ if (backgroundRefresh)
435
+ return;
436
+ backgroundRefresh = loadFromNetwork()
437
+ .catch((err) => {
438
+ failedAt = Date.now();
439
+ console.warn(`[plumbus/ai-bedrock] Price List refresh failed: ${err instanceof Error ? err.message : String(err)}`);
440
+ })
441
+ .finally(() => {
442
+ backgroundRefresh = null;
443
+ });
444
+ }
445
+ async function warm() {
446
+ if (options.pricingFilePath) {
447
+ if (rates.size > 0 && loadedAt > 0)
448
+ return;
449
+ await loadFromFile(options.pricingFilePath);
450
+ return;
451
+ }
452
+ if (loadedAt === 0) {
453
+ // Never loaded. Back off after a failure so a blocked pricing CDN does not
454
+ // add the fetch timeout to every single inference request.
455
+ if (failedAt > 0 && Date.now() - failedAt < FAILED_REFRESH_COOLDOWN_MS)
456
+ return;
457
+ await loadFromNetwork();
458
+ return;
459
+ }
460
+ // Rates already in hand: refresh off the request path once the TTL expires.
461
+ if (Date.now() - loadedAt > ttlMs)
462
+ refreshInBackground();
463
+ }
464
+ return {
465
+ warm: () => {
466
+ if (!warmPromise) {
467
+ warmPromise = warm().finally(() => {
468
+ warmPromise = null;
469
+ });
470
+ }
471
+ return warmPromise;
472
+ },
473
+ getRate: lookup,
474
+ listRates: () => [...rates.entries()].map(([id, rate]) => ({ id, rate })),
475
+ calculateCost: (modelId, usage) => {
476
+ const rate = lookup(modelId);
477
+ if (!rate)
478
+ return undefined;
479
+ // `global.` inference profiles are billed below the regional rate. Fall
480
+ // back to regional when the file/offer has no global row.
481
+ const isGlobalProfile = /^global\./i.test(modelId.trim());
482
+ const inputPerMTok = (isGlobalProfile ? rate.globalInputPerMTok : undefined) ?? rate.inputPerMTok;
483
+ const outputPerMTok = (isGlobalProfile ? rate.globalOutputPerMTok : undefined) ?? rate.outputPerMTok;
484
+ const cached = usage.cachedInputTokens ?? 0;
485
+ const cacheWrites = usage.cacheWriteTokens ?? 0;
486
+ // Bedrock's `inputTokens` already EXCLUDES cache read/write tokens
487
+ // ("total input tokens = inputTokens + cacheReadInputTokens +
488
+ // cacheWriteInputTokens" — AWS prompt-caching docs), so they are billed
489
+ // additively here, never subtracted out of `inputTokens`.
490
+ const standardInput = Math.max(0, usage.inputTokens);
491
+ // Published cache rates when known; otherwise approximate Anthropic-style
492
+ // multipliers against the input rate.
493
+ const cacheReadRate = rate.cacheReadPerMTok ?? inputPerMTok * 0.1;
494
+ const cacheWriteRate = rate.cacheWritePerMTok ?? inputPerMTok * 1.25;
495
+ const inputCost = standardInput * inputPerMTok + cached * cacheReadRate + cacheWrites * cacheWriteRate;
496
+ const outputCost = usage.outputTokens * outputPerMTok;
497
+ return Number(((inputCost + outputCost) / 1_000_000).toFixed(10));
498
+ },
499
+ };
500
+ }
501
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}