@mastra/observability 1.17.1-alpha.0 → 1.17.1-alpha.2
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/CHANGELOG.md +18 -0
- package/README.md +3 -1
- package/dist/index.cjs +104 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +104 -13
- package/dist/index.js.map +1 -1
- package/dist/metrics/estimator.d.ts.map +1 -1
- package/dist/metrics/pricing-registry.d.ts.map +1 -1
- package/dist/metrics/types.d.ts +4 -0
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/metrics/usage-metrics.d.ts.map +1 -1
- package/dist/spans/serialization.d.ts.map +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @mastra/observability
|
|
2
2
|
|
|
3
|
+
## 1.17.1-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed the `__truncated` marker on span data. It now counts only the fields dropped by the object-key limit, so traces no longer report more omitted keys than were really dropped. Values beyond the limit are no longer read. ([#21630](https://github.com/mastra-ai/mastra/pull/21630))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`4e7a421`](https://github.com/mastra-ai/mastra/commit/4e7a421dce8a48742f785d1e93ad2f43a572b282), [`242e324`](https://github.com/mastra-ai/mastra/commit/242e3241e73cbd5c9bb86a31ebb49ca0256488d4), [`217e967`](https://github.com/mastra-ai/mastra/commit/217e9672d8b3160eb729d8e9f0044949e88da239), [`d774e89`](https://github.com/mastra-ai/mastra/commit/d774e8930c781df8c9effe3763e6b501c099b6cc), [`9c27a53`](https://github.com/mastra-ai/mastra/commit/9c27a53cd9d3de4f3f025bc387d94ce371c33f95), [`dff25a1`](https://github.com/mastra-ai/mastra/commit/dff25a1103fa72ee082a9b6f805ebeb5ce400753), [`217e967`](https://github.com/mastra-ai/mastra/commit/217e9672d8b3160eb729d8e9f0044949e88da239), [`7f78585`](https://github.com/mastra-ai/mastra/commit/7f785857e401570e2ffb316911f126ed363aa537), [`f2a4afd`](https://github.com/mastra-ai/mastra/commit/f2a4afd7e37e809669001ed17724b341a5c1f45e), [`d438148`](https://github.com/mastra-ai/mastra/commit/d438148e222c1e2fb3c652725ce75680962ebec4), [`ba05fe0`](https://github.com/mastra-ai/mastra/commit/ba05fe0738f70cb686777546e968237d09269142), [`d26a8d4`](https://github.com/mastra-ai/mastra/commit/d26a8d4281f28414715b333c85bedaf70d0b2890), [`677cdc6`](https://github.com/mastra-ai/mastra/commit/677cdc6af564dec29a13464d12b7ab2a4efc22e9), [`a318490`](https://github.com/mastra-ai/mastra/commit/a318490e17da32f338d50929c770d901a9b3dd72), [`763e0c6`](https://github.com/mastra-ai/mastra/commit/763e0c61e04d76ad9a9efd301aa57525ca0cbea9), [`23e0be2`](https://github.com/mastra-ai/mastra/commit/23e0be261381e49534b4ff3101c60ee64a946cbf), [`7fc8806`](https://github.com/mastra-ai/mastra/commit/7fc880627d3cbf995d31ea0e8b807bf15417e651), [`0e02eac`](https://github.com/mastra-ai/mastra/commit/0e02eacdb2e30e1697a41910b41163742a181dc1), [`4df174c`](https://github.com/mastra-ai/mastra/commit/4df174c32bddf093a82f273070b8380aef7c9e90), [`f7c25b5`](https://github.com/mastra-ai/mastra/commit/f7c25b5106ddfb48e591f98df7a51e0f2dd01dba), [`dc09cc1`](https://github.com/mastra-ai/mastra/commit/dc09cc1083d861cde192c1cd235324dc75b8c731), [`36b4649`](https://github.com/mastra-ai/mastra/commit/36b4649045a3a380cbab8ceca866db4086223aff), [`377eb81`](https://github.com/mastra-ai/mastra/commit/377eb81ce43b964e3a6b541df172da74a8ff3716)]:
|
|
10
|
+
- @mastra/core@1.60.0-alpha.8
|
|
11
|
+
|
|
12
|
+
## 1.17.1-alpha.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Fixed Anthropic cache-write cost estimates by applying TTL-specific rates without double counting aggregate tokens. ([#21563](https://github.com/mastra-ai/mastra/pull/21563))
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [[`d7e6745`](https://github.com/mastra-ai/mastra/commit/d7e67456954863c55440ea9c49bc6ceb9949972d), [`9acb50f`](https://github.com/mastra-ai/mastra/commit/9acb50f71cec9c362f06820033f90ae6b1f8282f), [`46e9e3f`](https://github.com/mastra-ai/mastra/commit/46e9e3f73babe1bc70080a596cf2ac0b9da48519), [`3f9a190`](https://github.com/mastra-ai/mastra/commit/3f9a19057c027155867b9317294ee4ca7bd0581a), [`e8808e3`](https://github.com/mastra-ai/mastra/commit/e8808e3d8eb585a2565be53e56a7e0e1477352a4), [`d4be8c1`](https://github.com/mastra-ai/mastra/commit/d4be8c1739d22d621e3f78790e1dd5eb5ecc3589), [`a5d2eb1`](https://github.com/mastra-ai/mastra/commit/a5d2eb10347eade1ae2816d88f466c25186c54a5), [`e81744c`](https://github.com/mastra-ai/mastra/commit/e81744cd13c46619c142dc521dc0baac47607a84)]:
|
|
19
|
+
- @mastra/core@1.60.0-alpha.4
|
|
20
|
+
|
|
3
21
|
## 1.17.1-alpha.0
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -56,9 +56,11 @@ Metrics are automatically extracted from span lifecycle events by `AutoExtracted
|
|
|
56
56
|
- `mastra_workflow_duration_ms`
|
|
57
57
|
- `mastra_model_duration_ms`
|
|
58
58
|
- `mastra_model_total_input_tokens` / `mastra_model_total_output_tokens`
|
|
59
|
-
- `mastra_model_input_text_tokens` / `mastra_model_input_cache_read_tokens` / `mastra_model_input_cache_write_tokens` / `mastra_model_input_audio_tokens` / `mastra_model_input_image_tokens`
|
|
59
|
+
- `mastra_model_input_text_tokens` / `mastra_model_input_cache_read_tokens` / `mastra_model_input_cache_write_tokens` / `mastra_model_input_cache_write_5m_tokens` / `mastra_model_input_cache_write_1h_tokens` / `mastra_model_input_audio_tokens` / `mastra_model_input_image_tokens`
|
|
60
60
|
- `mastra_model_output_text_tokens` / `mastra_model_output_reasoning_tokens` / `mastra_model_output_audio_tokens` / `mastra_model_output_image_tokens`
|
|
61
61
|
|
|
62
|
+
For Anthropic models, the aggregate cache-write metric remains available while the 5-minute and 1-hour metrics preserve the provider's TTL-specific token counts and pricing.
|
|
63
|
+
|
|
62
64
|
Auto-extracted metrics carry labels: `entity_type`, `entity_name`, `status`, plus `model` and `provider` on model generation spans.
|
|
63
65
|
|
|
64
66
|
### Structured logging
|
package/dist/index.cjs
CHANGED
|
@@ -217,6 +217,12 @@ const LOGGER_METHODS = [
|
|
|
217
217
|
"warn",
|
|
218
218
|
"error"
|
|
219
219
|
];
|
|
220
|
+
/** Keys whose value decides the outcome in `shouldStripEntry()`. */
|
|
221
|
+
const VALUE_STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
222
|
+
"logger",
|
|
223
|
+
"tracingContext",
|
|
224
|
+
...FUNCTION_KEYS_TO_STRIP
|
|
225
|
+
]);
|
|
220
226
|
const DEFAULT_DEEP_CLEAN_OPTIONS = Object.freeze({
|
|
221
227
|
keysToStrip: [],
|
|
222
228
|
maxDepth: 8,
|
|
@@ -298,6 +304,25 @@ function shouldStripEntry(key, value, stripSet) {
|
|
|
298
304
|
if (key === "logger") return typeof value === "function" || isLoggerLike(value);
|
|
299
305
|
return FUNCTION_KEYS_TO_STRIP.has(key) && typeof value === "function";
|
|
300
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Whether an entry past the object-key limit would have been stripped anyway.
|
|
309
|
+
*
|
|
310
|
+
* The entry is dropped either way, so the value is taken from its property descriptor
|
|
311
|
+
* rather than read: a getter must not run for data that is being discarded. That keeps
|
|
312
|
+
* the truncation count the same wherever a runtime-shaped key sits. An accessor cannot
|
|
313
|
+
* be classified without invoking it, so it is left to the limit and counted.
|
|
314
|
+
*/
|
|
315
|
+
function wouldBeStripped(key, val, stripSet) {
|
|
316
|
+
if (!VALUE_STRIP_KEYS.has(key)) return false;
|
|
317
|
+
let descriptor;
|
|
318
|
+
try {
|
|
319
|
+
descriptor = Object.getOwnPropertyDescriptor(val, key);
|
|
320
|
+
} catch {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
if (!descriptor || !("value" in descriptor)) return false;
|
|
324
|
+
return shouldStripEntry(key, descriptor.value, stripSet);
|
|
325
|
+
}
|
|
301
326
|
function restoreSerializedMapKey(keyType, key) {
|
|
302
327
|
switch (keyType) {
|
|
303
328
|
case "undefined": return;
|
|
@@ -483,25 +508,22 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
|
483
508
|
return formatSerializationError(error);
|
|
484
509
|
}
|
|
485
510
|
let keyCount = 0;
|
|
511
|
+
let omittedByLimit = 0;
|
|
486
512
|
for (const key of keys) {
|
|
487
513
|
if (stripSet.has(key)) continue;
|
|
514
|
+
if (keyCount >= maxObjectKeys) {
|
|
515
|
+
if (!wouldBeStripped(key, val, stripSet)) omittedByLimit++;
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
488
518
|
let rawValue;
|
|
489
519
|
try {
|
|
490
520
|
rawValue = val[key];
|
|
491
521
|
} catch (error) {
|
|
492
|
-
if (keyCount >= maxObjectKeys) {
|
|
493
|
-
cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
522
|
cleaned[key] = formatSerializationError(error);
|
|
497
523
|
keyCount++;
|
|
498
524
|
continue;
|
|
499
525
|
}
|
|
500
526
|
if (shouldStripEntry(key, rawValue, stripSet)) continue;
|
|
501
|
-
if (keyCount >= maxObjectKeys) {
|
|
502
|
-
cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
527
|
try {
|
|
506
528
|
cleaned[key] = helper(rawValue, depth + 1);
|
|
507
529
|
keyCount++;
|
|
@@ -510,6 +532,7 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
|
510
532
|
keyCount++;
|
|
511
533
|
}
|
|
512
534
|
}
|
|
535
|
+
if (omittedByLimit > 0) cleaned["__truncated"] = `${omittedByLimit} more keys omitted`;
|
|
513
536
|
return cleaned;
|
|
514
537
|
} finally {
|
|
515
538
|
if (typeof val === "object" && val !== null) ancestors.delete(val);
|
|
@@ -1102,6 +1125,8 @@ const MINIFIED_METER_TO_CANONICAL = {
|
|
|
1102
1125
|
ot: "output_tokens",
|
|
1103
1126
|
icrt: "input_cache_read_tokens",
|
|
1104
1127
|
icwt: "input_cache_write_tokens",
|
|
1128
|
+
icwt5m: "input_cache_write_5m_tokens",
|
|
1129
|
+
icwt1h: "input_cache_write_1h_tokens",
|
|
1105
1130
|
iat: "input_audio_tokens",
|
|
1106
1131
|
oat: "output_audio_tokens",
|
|
1107
1132
|
ort: "output_reasoning_tokens"
|
|
@@ -1158,6 +1183,15 @@ function parsePricingModelText(content) {
|
|
|
1158
1183
|
}
|
|
1159
1184
|
return pricingModels;
|
|
1160
1185
|
}
|
|
1186
|
+
function expandRates(row, tier) {
|
|
1187
|
+
const rates = Object.fromEntries(Object.entries(tier.r).map(([meter, value]) => [MINIFIED_METER_TO_CANONICAL[meter], value.c]));
|
|
1188
|
+
const cacheWriteRate = rates.input_cache_write_tokens;
|
|
1189
|
+
if (row.m.includes("claude") && typeof cacheWriteRate === "number") {
|
|
1190
|
+
rates.input_cache_write_5m_tokens ??= cacheWriteRate;
|
|
1191
|
+
rates.input_cache_write_1h_tokens ??= cacheWriteRate * 1.6;
|
|
1192
|
+
}
|
|
1193
|
+
return rates;
|
|
1194
|
+
}
|
|
1161
1195
|
function expandPricingModelRow(row) {
|
|
1162
1196
|
return new PricingModel({
|
|
1163
1197
|
id: row.i,
|
|
@@ -1172,7 +1206,7 @@ function expandPricingModelRow(row) {
|
|
|
1172
1206
|
op: condition.op,
|
|
1173
1207
|
value: condition.value
|
|
1174
1208
|
})),
|
|
1175
|
-
rates:
|
|
1209
|
+
rates: expandRates(row, tier)
|
|
1176
1210
|
}))
|
|
1177
1211
|
});
|
|
1178
1212
|
}
|
|
@@ -1303,6 +1337,8 @@ const PricingMeter = {
|
|
|
1303
1337
|
INPUT_AUDIO_TOKENS: "input_audio_tokens",
|
|
1304
1338
|
INPUT_CACHE_READ_TOKENS: "input_cache_read_tokens",
|
|
1305
1339
|
INPUT_CACHE_WRITE_TOKENS: "input_cache_write_tokens",
|
|
1340
|
+
INPUT_CACHE_WRITE_5M_TOKENS: "input_cache_write_5m_tokens",
|
|
1341
|
+
INPUT_CACHE_WRITE_1H_TOKENS: "input_cache_write_1h_tokens",
|
|
1306
1342
|
INPUT_IMAGE_TOKENS: "input_image_tokens",
|
|
1307
1343
|
OUTPUT_TOKENS: "output_tokens",
|
|
1308
1344
|
OUTPUT_AUDIO_TOKENS: "output_audio_tokens",
|
|
@@ -1315,6 +1351,8 @@ const TokenMetrics = {
|
|
|
1315
1351
|
INPUT_TEXT: "mastra_model_input_text_tokens",
|
|
1316
1352
|
INPUT_CACHE_READ: "mastra_model_input_cache_read_tokens",
|
|
1317
1353
|
INPUT_CACHE_WRITE: "mastra_model_input_cache_write_tokens",
|
|
1354
|
+
INPUT_CACHE_WRITE_5M: "mastra_model_input_cache_write_5m_tokens",
|
|
1355
|
+
INPUT_CACHE_WRITE_1H: "mastra_model_input_cache_write_1h_tokens",
|
|
1318
1356
|
INPUT_AUDIO: "mastra_model_input_audio_tokens",
|
|
1319
1357
|
INPUT_IMAGE: "mastra_model_input_image_tokens",
|
|
1320
1358
|
OUTPUT_TEXT: "mastra_model_output_text_tokens",
|
|
@@ -1344,6 +1382,8 @@ function getTokenMetricSamples(usage) {
|
|
|
1344
1382
|
pushIfPositive(TokenMetrics.INPUT_TEXT, usage.inputDetails.text);
|
|
1345
1383
|
pushIfPositive(TokenMetrics.INPUT_CACHE_READ, usage.inputDetails.cacheRead);
|
|
1346
1384
|
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE, usage.inputDetails.cacheWrite);
|
|
1385
|
+
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE_5M, usage.inputDetails.cacheWrite5m);
|
|
1386
|
+
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE_1H, usage.inputDetails.cacheWrite1h);
|
|
1347
1387
|
pushIfPositive(TokenMetrics.INPUT_AUDIO, usage.inputDetails.audio);
|
|
1348
1388
|
pushIfPositive(TokenMetrics.INPUT_IMAGE, usage.inputDetails.image);
|
|
1349
1389
|
}
|
|
@@ -1410,15 +1450,40 @@ function estimateCosts(args, pricingRegistry = PricingRegistry.getGlobal()) {
|
|
|
1410
1450
|
results.set(TokenMetrics.INPUT_CACHE_READ, result.costContext);
|
|
1411
1451
|
inputDetailResults.push(result);
|
|
1412
1452
|
}
|
|
1413
|
-
|
|
1453
|
+
const cacheWriteDetailResults = [];
|
|
1454
|
+
const cacheWrite5m = usage.inputDetails?.cacheWrite5m ?? 0;
|
|
1455
|
+
const cacheWrite1h = usage.inputDetails?.cacheWrite1h ?? 0;
|
|
1456
|
+
if (cacheWrite5m > 0) {
|
|
1457
|
+
const result = estimateCostForMeter({
|
|
1458
|
+
meter: PricingMeter.INPUT_CACHE_WRITE_5M_TOKENS,
|
|
1459
|
+
tokenCount: cacheWrite5m,
|
|
1460
|
+
...estimateFields
|
|
1461
|
+
});
|
|
1462
|
+
results.set(TokenMetrics.INPUT_CACHE_WRITE_5M, result.costContext);
|
|
1463
|
+
cacheWriteDetailResults.push(result);
|
|
1464
|
+
inputDetailResults.push(result);
|
|
1465
|
+
}
|
|
1466
|
+
if (cacheWrite1h > 0) {
|
|
1467
|
+
const result = estimateCostForMeter({
|
|
1468
|
+
meter: PricingMeter.INPUT_CACHE_WRITE_1H_TOKENS,
|
|
1469
|
+
tokenCount: cacheWrite1h,
|
|
1470
|
+
...estimateFields
|
|
1471
|
+
});
|
|
1472
|
+
results.set(TokenMetrics.INPUT_CACHE_WRITE_1H, result.costContext);
|
|
1473
|
+
cacheWriteDetailResults.push(result);
|
|
1474
|
+
inputDetailResults.push(result);
|
|
1475
|
+
}
|
|
1476
|
+
const unclassifiedCacheWrite = Math.max(0, (usage.inputDetails?.cacheWrite ?? 0) - cacheWrite5m - cacheWrite1h);
|
|
1477
|
+
if (unclassifiedCacheWrite > 0) {
|
|
1414
1478
|
const result = estimateCostForMeter({
|
|
1415
1479
|
meter: PricingMeter.INPUT_CACHE_WRITE_TOKENS,
|
|
1416
|
-
tokenCount:
|
|
1480
|
+
tokenCount: unclassifiedCacheWrite,
|
|
1417
1481
|
...estimateFields
|
|
1418
1482
|
});
|
|
1419
|
-
|
|
1483
|
+
cacheWriteDetailResults.push(result);
|
|
1420
1484
|
inputDetailResults.push(result);
|
|
1421
1485
|
}
|
|
1486
|
+
if (cacheWriteDetailResults.length > 0) setCombinedCostContext(results, TokenMetrics.INPUT_CACHE_WRITE, cacheWriteDetailResults, pricingModel, costMetadata);
|
|
1422
1487
|
if (usage.inputDetails?.image) {
|
|
1423
1488
|
const result = estimateCostForMeter({
|
|
1424
1489
|
meter: PricingMeter.INPUT_IMAGE_TOKENS,
|
|
@@ -1495,6 +1560,20 @@ function estimateCosts(args, pricingRegistry = PricingRegistry.getGlobal()) {
|
|
|
1495
1560
|
function applyErrorContextForUsage(results, usage, errorContext) {
|
|
1496
1561
|
for (const sample of getTokenMetricSamples(usage)) results.set(sample.name, errorContext);
|
|
1497
1562
|
}
|
|
1563
|
+
function setCombinedCostContext(results, metric, detailResults, pricingModel, costMetadata) {
|
|
1564
|
+
const estimatedCosts = detailResults.map((result) => result.costContext.estimatedCost).filter((value) => typeof value === "number");
|
|
1565
|
+
const hasFailedCost = detailResults.some((result) => !result.success);
|
|
1566
|
+
results.set(metric, {
|
|
1567
|
+
provider: pricingModel.provider,
|
|
1568
|
+
model: pricingModel.model,
|
|
1569
|
+
...estimatedCosts.length > 0 && { estimatedCost: estimatedCosts.reduce((sum, value) => sum + value, 0) },
|
|
1570
|
+
...estimatedCosts.length > 0 && { costUnit: pricingModel.currency },
|
|
1571
|
+
costMetadata: hasFailedCost ? {
|
|
1572
|
+
...costMetadata,
|
|
1573
|
+
error: "partial_cost"
|
|
1574
|
+
} : { ...costMetadata }
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1498
1577
|
function setAggregateCostContext(args) {
|
|
1499
1578
|
const { results, totalMetric, fallbackMeter, totalTokenCount, detailResults, pricingModel, pricingTier, costMetadata } = args;
|
|
1500
1579
|
if (totalTokenCount == null) return;
|
|
@@ -1735,14 +1814,24 @@ function extractUsageMetrics(usage, providerMetadata) {
|
|
|
1735
1814
|
if (isDefined(aiSdkDetails?.cacheReadTokens)) inputDetails.cacheRead = aiSdkDetails.cacheReadTokens;
|
|
1736
1815
|
if (isDefined(aiSdkDetails?.cacheWriteTokens)) inputDetails.cacheWrite = aiSdkDetails.cacheWriteTokens;
|
|
1737
1816
|
if (!isDefined(inputDetails.cacheRead) && isDefined(usage.cachedInputTokens)) inputDetails.cacheRead = usage.cachedInputTokens;
|
|
1817
|
+
if (isDefined(usage.cacheCreationInputTokens5m)) inputDetails.cacheWrite5m = usage.cacheCreationInputTokens5m;
|
|
1818
|
+
if (isDefined(usage.cacheCreationInputTokens1h)) inputDetails.cacheWrite1h = usage.cacheCreationInputTokens1h;
|
|
1738
1819
|
if (!isDefined(inputDetails.cacheWrite) && isDefined(usage.cacheCreationInputTokens)) inputDetails.cacheWrite = usage.cacheCreationInputTokens;
|
|
1820
|
+
if (!isDefined(inputDetails.cacheWrite) && (isDefined(inputDetails.cacheWrite5m) || isDefined(inputDetails.cacheWrite1h))) inputDetails.cacheWrite = (inputDetails.cacheWrite5m ?? 0) + (inputDetails.cacheWrite1h ?? 0);
|
|
1739
1821
|
if (isDefined(usage.reasoningTokens)) outputDetails.reasoning = usage.reasoningTokens;
|
|
1740
1822
|
const anthropic = providerMetadata?.anthropic;
|
|
1741
1823
|
if (anthropic) {
|
|
1742
1824
|
const rawV3InputUsage = isV3RawUsage(usage.raw) ? usage.raw.inputTokens : void 0;
|
|
1743
1825
|
const hasV3CachedTotals = rawV3InputUsage?.total !== void 0 && (rawV3InputUsage.cacheRead !== void 0 || rawV3InputUsage.cacheWrite !== void 0);
|
|
1744
1826
|
if (!isDefined(inputDetails.cacheRead) && isDefined(anthropic.cacheReadInputTokens)) inputDetails.cacheRead = anthropic.cacheReadInputTokens;
|
|
1745
|
-
|
|
1827
|
+
const cacheWrite5m = anthropic.cacheCreation?.ephemeral_5m_input_tokens ?? anthropic.cacheCreation?.ephemeral5mInputTokens;
|
|
1828
|
+
const cacheWrite1h = anthropic.cacheCreation?.ephemeral_1h_input_tokens ?? anthropic.cacheCreation?.ephemeral1hInputTokens;
|
|
1829
|
+
if (!isDefined(inputDetails.cacheWrite5m) && isDefined(cacheWrite5m)) inputDetails.cacheWrite5m = cacheWrite5m;
|
|
1830
|
+
if (!isDefined(inputDetails.cacheWrite1h) && isDefined(cacheWrite1h)) inputDetails.cacheWrite1h = cacheWrite1h;
|
|
1831
|
+
if (!isDefined(inputDetails.cacheWrite)) {
|
|
1832
|
+
if (isDefined(anthropic.cacheCreationInputTokens)) inputDetails.cacheWrite = anthropic.cacheCreationInputTokens;
|
|
1833
|
+
else if (isDefined(cacheWrite5m) || isDefined(cacheWrite1h)) inputDetails.cacheWrite = (cacheWrite5m ?? 0) + (cacheWrite1h ?? 0);
|
|
1834
|
+
}
|
|
1746
1835
|
if (!(hasV3CachedTotals || isDefined(usage.cachedInputTokens) && usage.cachedInputTokens > 0 || isDefined(usage.cacheCreationInputTokens) && usage.cacheCreationInputTokens > 0) && (isDefined(inputDetails.cacheRead) || isDefined(inputDetails.cacheWrite))) inputTokens = (usage.inputTokens ?? 0) + (inputDetails.cacheRead ?? 0) + (inputDetails.cacheWrite ?? 0);
|
|
1747
1836
|
}
|
|
1748
1837
|
const google = providerMetadata?.google;
|
|
@@ -1783,6 +1872,8 @@ function mergeInputDetails(a, b) {
|
|
|
1783
1872
|
text: addOptional(a.text, b.text),
|
|
1784
1873
|
cacheRead: addOptional(a.cacheRead, b.cacheRead),
|
|
1785
1874
|
cacheWrite: addOptional(a.cacheWrite, b.cacheWrite),
|
|
1875
|
+
cacheWrite5m: addOptional(a.cacheWrite5m, b.cacheWrite5m),
|
|
1876
|
+
cacheWrite1h: addOptional(a.cacheWrite1h, b.cacheWrite1h),
|
|
1786
1877
|
audio: addOptional(a.audio, b.audio),
|
|
1787
1878
|
image: addOptional(a.image, b.image)
|
|
1788
1879
|
};
|