@usagetap/sdk 1.4.0 → 1.7.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.
- package/README.md +156 -18
- package/dist/adapters/anthropic.cjs +195 -235
- package/dist/adapters/anthropic.cjs.map +1 -1
- package/dist/adapters/anthropic.d.cts +1 -1
- package/dist/adapters/anthropic.d.ts +1 -1
- package/dist/adapters/anthropic.mjs +195 -235
- package/dist/adapters/anthropic.mjs.map +1 -1
- package/dist/adapters/openai.cjs +256 -274
- package/dist/adapters/openai.cjs.map +1 -1
- package/dist/adapters/openai.d.cts +1 -1
- package/dist/adapters/openai.d.ts +1 -1
- package/dist/adapters/openai.mjs +256 -274
- package/dist/adapters/openai.mjs.map +1 -1
- package/dist/adapters/openrouter.cjs +256 -274
- package/dist/adapters/openrouter.cjs.map +1 -1
- package/dist/adapters/openrouter.d.cts +1 -1
- package/dist/adapters/openrouter.d.ts +1 -1
- package/dist/adapters/openrouter.mjs +256 -274
- package/dist/adapters/openrouter.mjs.map +1 -1
- package/dist/anthropic/index.cjs +195 -235
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.d.cts +1 -1
- package/dist/anthropic/index.d.ts +1 -1
- package/dist/anthropic/index.mjs +195 -235
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/{client-CExQ8e1T.d.cts → client-C0UiaqVB.d.cts} +141 -61
- package/dist/{client-CExQ8e1T.d.ts → client-C0UiaqVB.d.ts} +141 -61
- package/dist/express/index.cjs +189 -246
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +1 -1
- package/dist/express/index.d.ts +1 -1
- package/dist/express/index.mjs +189 -246
- package/dist/express/index.mjs.map +1 -1
- package/dist/index.cjs +391 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -4
- package/dist/index.d.ts +13 -4
- package/dist/index.mjs +391 -175
- package/dist/index.mjs.map +1 -1
- package/dist/openai/index.cjs +256 -274
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.d.cts +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.mjs +256 -274
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openrouter/index.cjs +256 -274
- package/dist/openrouter/index.cjs.map +1 -1
- package/dist/openrouter/index.d.cts +1 -1
- package/dist/openrouter/index.d.ts +1 -1
- package/dist/openrouter/index.mjs +256 -274
- package/dist/openrouter/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/anthropic/index.cjs
CHANGED
|
@@ -1024,6 +1024,8 @@ var SummarizationResource = class {
|
|
|
1024
1024
|
};
|
|
1025
1025
|
var GatewayResource = class {
|
|
1026
1026
|
chat;
|
|
1027
|
+
/** Buffered OpenAI Responses-compatible requests. */
|
|
1028
|
+
responses;
|
|
1027
1029
|
models;
|
|
1028
1030
|
batches;
|
|
1029
1031
|
transport;
|
|
@@ -1045,6 +1047,15 @@ var GatewayResource = class {
|
|
|
1045
1047
|
})
|
|
1046
1048
|
}
|
|
1047
1049
|
};
|
|
1050
|
+
this.responses = {
|
|
1051
|
+
create: (params, options) => this.transport.request({
|
|
1052
|
+
method: "POST",
|
|
1053
|
+
path: "/v1/responses",
|
|
1054
|
+
body: params,
|
|
1055
|
+
options,
|
|
1056
|
+
response: "json"
|
|
1057
|
+
})
|
|
1058
|
+
};
|
|
1048
1059
|
this.models = {
|
|
1049
1060
|
list: (options) => this.transport.request({
|
|
1050
1061
|
method: "GET",
|
|
@@ -1130,7 +1141,7 @@ var USER_AGENT = "UsageTapClient";
|
|
|
1130
1141
|
var CANONICAL_MEDIA_TYPE2 = "application/vnd.usagetap.v1+json";
|
|
1131
1142
|
var DEFAULT_BASE_URL = "https://api.usagetap.com";
|
|
1132
1143
|
var DEFAULT_RUN_INACTIVITY_MS = 60 * 60 * 1e3;
|
|
1133
|
-
var SDK_VERSION = "1.
|
|
1144
|
+
var SDK_VERSION = "1.7.0" ;
|
|
1134
1145
|
var HAS_WINDOW = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
|
|
1135
1146
|
var UsageTapClient = class {
|
|
1136
1147
|
/** OpenAI-compatible chat, model, and native batch operations. */
|
|
@@ -1532,9 +1543,18 @@ var UsageTapClient = class {
|
|
|
1532
1543
|
responseTokens: request.responseTokens,
|
|
1533
1544
|
cachedInputTokens: request.cachedInputTokens,
|
|
1534
1545
|
cacheWriteInputTokens: request.cacheWriteInputTokens,
|
|
1546
|
+
cacheWrite5mInputTokens: request.cacheWrite5mInputTokens,
|
|
1547
|
+
cacheWrite1hInputTokens: request.cacheWrite1hInputTokens,
|
|
1535
1548
|
reasoningTokens: request.reasoningTokens,
|
|
1536
1549
|
searches: request.searches,
|
|
1537
1550
|
audioSeconds: request.audioSeconds,
|
|
1551
|
+
imageInputCount: request.imageInputCount,
|
|
1552
|
+
imageInputTokens: request.imageInputTokens,
|
|
1553
|
+
imageOutputCount: request.imageOutputCount,
|
|
1554
|
+
imageOutputTokens: request.imageOutputTokens,
|
|
1555
|
+
audioInputTokens: request.audioInputTokens,
|
|
1556
|
+
cachedAudioInputTokens: request.cachedAudioInputTokens,
|
|
1557
|
+
audioOutputTokens: request.audioOutputTokens,
|
|
1538
1558
|
costUsd: response.data.costUSD
|
|
1539
1559
|
},
|
|
1540
1560
|
correlationId: response.correlationId
|
|
@@ -1621,10 +1641,10 @@ var UsageTapClient = class {
|
|
|
1621
1641
|
"incrementCustomMeter requires meterSlot"
|
|
1622
1642
|
);
|
|
1623
1643
|
}
|
|
1624
|
-
if (!["CUSTOM1", "CUSTOM2"].includes(request.meterSlot)) {
|
|
1644
|
+
if (!["CUSTOM1", "CUSTOM2", "AGENTIC_API"].includes(request.meterSlot)) {
|
|
1625
1645
|
throw new UsageTapError(
|
|
1626
1646
|
"USAGETAP_BAD_REQUEST",
|
|
1627
|
-
"meterSlot must be CUSTOM1 or
|
|
1647
|
+
"meterSlot must be CUSTOM1, CUSTOM2 or AGENTIC_API"
|
|
1628
1648
|
);
|
|
1629
1649
|
}
|
|
1630
1650
|
if (typeof request.amount !== "number" || !Number.isFinite(request.amount) || request.amount <= 0) {
|
|
@@ -1697,6 +1717,28 @@ var UsageTapClient = class {
|
|
|
1697
1717
|
let handlerResult;
|
|
1698
1718
|
let handlerError;
|
|
1699
1719
|
let endCallError;
|
|
1720
|
+
let finalizationDeferred = false;
|
|
1721
|
+
let finalizationPromise;
|
|
1722
|
+
const finalize = () => {
|
|
1723
|
+
if (!finalizationPromise) {
|
|
1724
|
+
finalizationPromise = this.endCall(
|
|
1725
|
+
{
|
|
1726
|
+
callId: beginResponse.data.callId,
|
|
1727
|
+
// Pass context for metric tracking
|
|
1728
|
+
customerId: beginRequest.customerId,
|
|
1729
|
+
feature: beginRequest.feature ?? this.defaultFeature,
|
|
1730
|
+
tags: beginRequest.tags ?? this.defaultTags,
|
|
1731
|
+
...usage,
|
|
1732
|
+
error: errorPayload
|
|
1733
|
+
},
|
|
1734
|
+
{
|
|
1735
|
+
...options,
|
|
1736
|
+
correlationId: beginResponse.correlationId
|
|
1737
|
+
}
|
|
1738
|
+
).then(() => void 0);
|
|
1739
|
+
}
|
|
1740
|
+
return finalizationPromise;
|
|
1741
|
+
};
|
|
1700
1742
|
const context = {
|
|
1701
1743
|
begin: beginResponse,
|
|
1702
1744
|
setUsage: (u) => {
|
|
@@ -1704,6 +1746,10 @@ var UsageTapClient = class {
|
|
|
1704
1746
|
},
|
|
1705
1747
|
setError: (err) => {
|
|
1706
1748
|
errorPayload = err;
|
|
1749
|
+
},
|
|
1750
|
+
deferFinalization: () => {
|
|
1751
|
+
finalizationDeferred = true;
|
|
1752
|
+
return finalize;
|
|
1707
1753
|
}
|
|
1708
1754
|
};
|
|
1709
1755
|
try {
|
|
@@ -1717,24 +1763,12 @@ var UsageTapClient = class {
|
|
|
1717
1763
|
};
|
|
1718
1764
|
}
|
|
1719
1765
|
} finally {
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
feature: beginRequest.feature ?? this.defaultFeature,
|
|
1727
|
-
tags: beginRequest.tags ?? this.defaultTags,
|
|
1728
|
-
...usage,
|
|
1729
|
-
error: errorPayload
|
|
1730
|
-
},
|
|
1731
|
-
{
|
|
1732
|
-
...options,
|
|
1733
|
-
correlationId: beginResponse.correlationId
|
|
1734
|
-
}
|
|
1735
|
-
);
|
|
1736
|
-
} catch (error) {
|
|
1737
|
-
endCallError = error;
|
|
1766
|
+
if (handlerError || !finalizationDeferred) {
|
|
1767
|
+
try {
|
|
1768
|
+
await finalize();
|
|
1769
|
+
} catch (error) {
|
|
1770
|
+
endCallError = error;
|
|
1771
|
+
}
|
|
1738
1772
|
}
|
|
1739
1773
|
}
|
|
1740
1774
|
if (handlerError) {
|
|
@@ -2076,7 +2110,8 @@ var UsageTapClient = class {
|
|
|
2076
2110
|
}
|
|
2077
2111
|
toHttpError(status, payload, correlationId) {
|
|
2078
2112
|
const code = mapStatusToErrorCode(status);
|
|
2079
|
-
const
|
|
2113
|
+
const apiCode = payload?.error?.code ?? payload?.result?.code ?? "UNKNOWN";
|
|
2114
|
+
const retryable = isRetryableStatus(status) || isRetryableApiCode(apiCode);
|
|
2080
2115
|
const message = payload?.error?.message ?? payload?.result?.message ?? `UsageTap responded with HTTP ${status}`;
|
|
2081
2116
|
return new UsageTapError(code, message, {
|
|
2082
2117
|
status,
|
|
@@ -2109,7 +2144,7 @@ function isRetryableStatus(status) {
|
|
|
2109
2144
|
}
|
|
2110
2145
|
function isRetryableApiCode(code) {
|
|
2111
2146
|
const normalized = code.toUpperCase();
|
|
2112
|
-
return normalized.includes("TRANSIENT") || normalized.includes("RETRY") || normalized.includes("TIMEOUT") || normalized.includes("THROTTLE") || normalized.includes("RATE_LIMIT");
|
|
2147
|
+
return normalized === "PAYG_CONFLICT" || normalized.includes("TRANSIENT") || normalized.includes("RETRY") || normalized.includes("TIMEOUT") || normalized.includes("THROTTLE") || normalized.includes("RATE_LIMIT");
|
|
2113
2148
|
}
|
|
2114
2149
|
function mapApiCodeToError(code) {
|
|
2115
2150
|
const normalized = code.toUpperCase();
|
|
@@ -2223,6 +2258,43 @@ var AnthropicPromptCompressionStats = class {
|
|
|
2223
2258
|
return this.totalOriginalCharacters > 0 ? this.totalCharactersSaved / this.totalOriginalCharacters : 0;
|
|
2224
2259
|
}
|
|
2225
2260
|
};
|
|
2261
|
+
var DeferredAnthropicApiPromise = class extends Promise {
|
|
2262
|
+
responseEnvelope;
|
|
2263
|
+
constructor(execute) {
|
|
2264
|
+
super((resolve) => resolve(void 0));
|
|
2265
|
+
this.responseEnvelope = Promise.resolve().then(execute);
|
|
2266
|
+
}
|
|
2267
|
+
then(onfulfilled, onrejected) {
|
|
2268
|
+
return this.responseEnvelope.then((result) => result.data).then(onfulfilled, onrejected);
|
|
2269
|
+
}
|
|
2270
|
+
catch(onrejected) {
|
|
2271
|
+
return this.then(void 0, onrejected);
|
|
2272
|
+
}
|
|
2273
|
+
finally(onfinally) {
|
|
2274
|
+
return this.responseEnvelope.then((result) => result.data).finally(onfinally ?? void 0);
|
|
2275
|
+
}
|
|
2276
|
+
withResponse() {
|
|
2277
|
+
return this.responseEnvelope;
|
|
2278
|
+
}
|
|
2279
|
+
async asResponse() {
|
|
2280
|
+
const result = await this.responseEnvelope;
|
|
2281
|
+
if (!("response" in result)) {
|
|
2282
|
+
throw new TypeError("The wrapped Anthropic result does not expose a raw response");
|
|
2283
|
+
}
|
|
2284
|
+
return result.response;
|
|
2285
|
+
}
|
|
2286
|
+
};
|
|
2287
|
+
async function resolveAnthropicResponseEnvelope(value) {
|
|
2288
|
+
if (isObjectRecord(value) && typeof value.withResponse === "function") {
|
|
2289
|
+
const withResponse = value.withResponse;
|
|
2290
|
+
const result = await withResponse.call(value);
|
|
2291
|
+
if (!isObjectRecord(result) || !("data" in result)) {
|
|
2292
|
+
throw new TypeError("Anthropic create().withResponse() returned an invalid result");
|
|
2293
|
+
}
|
|
2294
|
+
return result;
|
|
2295
|
+
}
|
|
2296
|
+
return { data: await value };
|
|
2297
|
+
}
|
|
2226
2298
|
var USAGETAP_CORRELATION_HEADER = "x-usage-correlation-id";
|
|
2227
2299
|
function withSampling(client, options = {}) {
|
|
2228
2300
|
if (!client?.messages || typeof client.messages.create !== "function" || !options) {
|
|
@@ -2235,53 +2307,56 @@ function withSampling(client, options = {}) {
|
|
|
2235
2307
|
const localPolicy = typeof policy.rate === "number" ? policy : void 0;
|
|
2236
2308
|
const usageTap = usageTapClient ?? new UsageTapClient({ apiKey, sampling: localPolicy });
|
|
2237
2309
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
2238
|
-
const create =
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
await
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2310
|
+
const create = (params, requestOptions) => {
|
|
2311
|
+
return new DeferredAnthropicApiPromise(async () => {
|
|
2312
|
+
const { usageTap: callContext = {}, ...providerOptions } = requestOptions ?? {};
|
|
2313
|
+
const decision = params.stream === true ? Promise.resolve(false) : usageTap.shouldSampleAsync({
|
|
2314
|
+
customerId: callContext.customerId,
|
|
2315
|
+
feature: callContext.feature,
|
|
2316
|
+
input: params
|
|
2317
|
+
}, localPolicy);
|
|
2318
|
+
const startedAt = Date.now();
|
|
2319
|
+
try {
|
|
2320
|
+
const result = await resolveAnthropicResponseEnvelope(originalCreate(
|
|
2321
|
+
params,
|
|
2322
|
+
Object.keys(providerOptions).length ? providerOptions : void 0
|
|
2323
|
+
));
|
|
2324
|
+
const response = result.data;
|
|
2325
|
+
const selected = await decision;
|
|
2326
|
+
if (selected) {
|
|
2327
|
+
const record = isObjectRecord(response) ? response : {};
|
|
2328
|
+
await usageTap.captureSample({
|
|
2329
|
+
customerId: callContext.customerId,
|
|
2330
|
+
feature: callContext.feature,
|
|
2331
|
+
environment: callContext.environment,
|
|
2332
|
+
tags: callContext.tags,
|
|
2333
|
+
provider: "anthropic",
|
|
2334
|
+
model: readString(record.model) ?? readString(params.model),
|
|
2335
|
+
input: params,
|
|
2336
|
+
output: response,
|
|
2337
|
+
usage: record.usage,
|
|
2338
|
+
latencyMs: Date.now() - startedAt
|
|
2339
|
+
}).catch(() => void 0);
|
|
2340
|
+
}
|
|
2341
|
+
return result;
|
|
2342
|
+
} catch (error) {
|
|
2343
|
+
const selected = await decision;
|
|
2344
|
+
if (selected) {
|
|
2345
|
+
await usageTap.captureSample({
|
|
2346
|
+
customerId: callContext.customerId,
|
|
2347
|
+
feature: callContext.feature,
|
|
2348
|
+
environment: callContext.environment,
|
|
2349
|
+
tags: callContext.tags,
|
|
2350
|
+
provider: "anthropic",
|
|
2351
|
+
model: readString(params.model),
|
|
2352
|
+
input: params,
|
|
2353
|
+
latencyMs: Date.now() - startedAt,
|
|
2354
|
+
error: error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) }
|
|
2355
|
+
}).catch(() => void 0);
|
|
2356
|
+
}
|
|
2357
|
+
throw error;
|
|
2282
2358
|
}
|
|
2283
|
-
|
|
2284
|
-
}
|
|
2359
|
+
});
|
|
2285
2360
|
};
|
|
2286
2361
|
const messages = new Proxy(client.messages, {
|
|
2287
2362
|
get(target, prop, receiver) {
|
|
@@ -2322,7 +2397,12 @@ function withCompression(client, options = {}) {
|
|
|
2322
2397
|
};
|
|
2323
2398
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
2324
2399
|
const wrappedCreate = (params, requestOptions) => {
|
|
2325
|
-
return
|
|
2400
|
+
return new DeferredAnthropicApiPromise(async () => {
|
|
2401
|
+
const outcome = await compressAnthropicParams(params, usageTap, compression);
|
|
2402
|
+
return resolveAnthropicResponseEnvelope(
|
|
2403
|
+
originalCreate(outcome.params, requestOptions)
|
|
2404
|
+
);
|
|
2405
|
+
});
|
|
2326
2406
|
};
|
|
2327
2407
|
const proxiedMessages = new Proxy(client.messages, {
|
|
2328
2408
|
get(target, prop, receiver) {
|
|
@@ -2417,20 +2497,22 @@ function createMessagesProxy(resource, usageTap, defaultContext, applyVendorHint
|
|
|
2417
2497
|
withUsage,
|
|
2418
2498
|
promptCompression
|
|
2419
2499
|
} = splitUsageOptions(options);
|
|
2420
|
-
return
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2500
|
+
return new DeferredAnthropicApiPromise(
|
|
2501
|
+
() => invokeMessagesCreate({
|
|
2502
|
+
params,
|
|
2503
|
+
requestOptions,
|
|
2504
|
+
usageContext,
|
|
2505
|
+
withUsage,
|
|
2506
|
+
promptCompression,
|
|
2507
|
+
originalCreate,
|
|
2508
|
+
usageTap,
|
|
2509
|
+
defaultContext,
|
|
2510
|
+
applyVendorHints,
|
|
2511
|
+
defaultPromptCompression,
|
|
2512
|
+
promptCompressionStats,
|
|
2513
|
+
defaultSampling
|
|
2514
|
+
})
|
|
2515
|
+
);
|
|
2434
2516
|
});
|
|
2435
2517
|
const handler = {
|
|
2436
2518
|
get(target, prop, receiver) {
|
|
@@ -2443,10 +2525,9 @@ function createMessagesProxy(resource, usageTap, defaultContext, applyVendorHint
|
|
|
2443
2525
|
return new Proxy(resource, handler);
|
|
2444
2526
|
}
|
|
2445
2527
|
async function invokeMessagesCreate(args) {
|
|
2446
|
-
const beginRequest =
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
String(args.params.model)
|
|
2528
|
+
const beginRequest = resolveBeginRequest(
|
|
2529
|
+
args.defaultContext,
|
|
2530
|
+
args.usageContext
|
|
2450
2531
|
);
|
|
2451
2532
|
const begin = await args.usageTap.beginCall(
|
|
2452
2533
|
beginRequest,
|
|
@@ -2477,17 +2558,23 @@ async function invokeMessagesCreate(args) {
|
|
|
2477
2558
|
});
|
|
2478
2559
|
ctx.setUsage(anthropicRequestExecutionMetadata(finalParams));
|
|
2479
2560
|
const request = attachCorrelationHeader(args.requestOptions, ctx.begin.correlationId);
|
|
2480
|
-
const
|
|
2561
|
+
const providerResult = await resolveAnthropicResponseEnvelope(
|
|
2562
|
+
args.originalCreate(finalParams, request)
|
|
2563
|
+
);
|
|
2564
|
+
const response = providerResult.data;
|
|
2481
2565
|
providerCompleted = true;
|
|
2482
2566
|
if (isStreamingRequest(finalParams)) {
|
|
2483
2567
|
ensureAsyncIterable(response, "messages.create");
|
|
2484
|
-
return
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2568
|
+
return {
|
|
2569
|
+
...providerResult,
|
|
2570
|
+
data: wrapAnthropicStreamForUsageTap(
|
|
2571
|
+
response,
|
|
2572
|
+
state,
|
|
2573
|
+
args.usageTap,
|
|
2574
|
+
args.withUsage,
|
|
2575
|
+
readString(finalParams.model)
|
|
2576
|
+
)
|
|
2577
|
+
};
|
|
2491
2578
|
}
|
|
2492
2579
|
inferAnthropicUsage(response, readString(finalParams.model), ctx);
|
|
2493
2580
|
await captureMeteredAnthropicSample({
|
|
@@ -2500,7 +2587,7 @@ async function invokeMessagesCreate(args) {
|
|
|
2500
2587
|
startedAt: sampleStartedAt
|
|
2501
2588
|
});
|
|
2502
2589
|
await finalizeCall(state, args.usageTap, args.withUsage);
|
|
2503
|
-
return
|
|
2590
|
+
return providerResult;
|
|
2504
2591
|
} catch (error) {
|
|
2505
2592
|
if (!state.error) {
|
|
2506
2593
|
state.error = {
|
|
@@ -2583,70 +2670,19 @@ async function captureMeteredAnthropicSample({
|
|
|
2583
2670
|
}).catch(() => void 0);
|
|
2584
2671
|
}
|
|
2585
2672
|
async function compressAnthropicParamsForCall(args) {
|
|
2586
|
-
|
|
2673
|
+
const compression = resolveEffectivePromptCompressionOptions(
|
|
2587
2674
|
args.defaultPromptCompression,
|
|
2588
2675
|
args.callPromptCompression
|
|
2589
2676
|
);
|
|
2590
|
-
const runtimePolicy = args.ctx.begin.data.runtimeCompressionPolicy;
|
|
2591
|
-
const policyDriven = !compression && Boolean(runtimePolicy);
|
|
2592
|
-
if (policyDriven && runtimePolicy) {
|
|
2593
|
-
if (!runtimePolicy.selected) {
|
|
2594
|
-
args.ctx.setUsage({
|
|
2595
|
-
runtimeCompression: bypassedRuntimeMeasurement(runtimePolicy)
|
|
2596
|
-
});
|
|
2597
|
-
return args.params;
|
|
2598
|
-
}
|
|
2599
|
-
compression = anthropicPolicyCompressionOptions(runtimePolicy);
|
|
2600
|
-
if (runtimePolicy.mode === "SHADOW") {
|
|
2601
|
-
const startedAt2 = Date.now();
|
|
2602
|
-
void compressAnthropicParams(
|
|
2603
|
-
args.params,
|
|
2604
|
-
args.usageTap,
|
|
2605
|
-
compression,
|
|
2606
|
-
args.withUsage?.signal
|
|
2607
|
-
).then((outcome2) => {
|
|
2608
|
-
args.ctx.setUsage({
|
|
2609
|
-
runtimeCompression: anthropicRuntimeMeasurement({
|
|
2610
|
-
policy: runtimePolicy,
|
|
2611
|
-
telemetry: buildPromptCompressionTelemetry(outcome2.segments),
|
|
2612
|
-
latencyMs: Date.now() - startedAt2,
|
|
2613
|
-
shadow: true,
|
|
2614
|
-
originalPayload: args.params,
|
|
2615
|
-
resultPayload: outcome2.params
|
|
2616
|
-
})
|
|
2617
|
-
});
|
|
2618
|
-
}).catch(() => {
|
|
2619
|
-
args.ctx.setUsage({
|
|
2620
|
-
runtimeCompression: failedRuntimeMeasurement(
|
|
2621
|
-
runtimePolicy,
|
|
2622
|
-
Date.now() - startedAt2
|
|
2623
|
-
)
|
|
2624
|
-
});
|
|
2625
|
-
});
|
|
2626
|
-
return args.params;
|
|
2627
|
-
}
|
|
2628
|
-
}
|
|
2629
2677
|
if (!compression) {
|
|
2630
2678
|
return args.params;
|
|
2631
2679
|
}
|
|
2632
|
-
const startedAt = Date.now();
|
|
2633
2680
|
const outcome = await compressAnthropicParams(
|
|
2634
2681
|
args.params,
|
|
2635
2682
|
args.usageTap,
|
|
2636
2683
|
compression,
|
|
2637
2684
|
args.withUsage?.signal
|
|
2638
2685
|
);
|
|
2639
|
-
if (policyDriven && runtimePolicy) {
|
|
2640
|
-
const runtimeMeasurement = anthropicRuntimeMeasurement({
|
|
2641
|
-
policy: runtimePolicy,
|
|
2642
|
-
telemetry: buildPromptCompressionTelemetry(outcome.segments),
|
|
2643
|
-
latencyMs: Date.now() - startedAt,
|
|
2644
|
-
originalPayload: args.params,
|
|
2645
|
-
resultPayload: outcome.params
|
|
2646
|
-
});
|
|
2647
|
-
args.ctx.setUsage({ runtimeCompression: runtimeMeasurement });
|
|
2648
|
-
if (runtimeMeasurement.decision !== "compressed") return args.params;
|
|
2649
|
-
}
|
|
2650
2686
|
await recordCompressionOutcome({
|
|
2651
2687
|
outcome,
|
|
2652
2688
|
compression,
|
|
@@ -2658,76 +2694,6 @@ async function compressAnthropicParamsForCall(args) {
|
|
|
2658
2694
|
});
|
|
2659
2695
|
return outcome.params;
|
|
2660
2696
|
}
|
|
2661
|
-
function anthropicPolicyCompressionOptions(policy) {
|
|
2662
|
-
const roles = Object.fromEntries(
|
|
2663
|
-
["system", "user", "tool", "assistant"].filter((role) => policy.snapshot.scope.messageRoles.includes(role)).map((role) => [role, true])
|
|
2664
|
-
);
|
|
2665
|
-
return {
|
|
2666
|
-
provider: "usagetap",
|
|
2667
|
-
roles,
|
|
2668
|
-
minContextTokens: policy.snapshot.scope.minimumTokens,
|
|
2669
|
-
failOpen: true
|
|
2670
|
-
};
|
|
2671
|
-
}
|
|
2672
|
-
function bypassedRuntimeMeasurement(policy) {
|
|
2673
|
-
return {
|
|
2674
|
-
policyId: policy.policyId,
|
|
2675
|
-
policyVersionId: policy.policyVersionId,
|
|
2676
|
-
policyVersion: policy.version,
|
|
2677
|
-
rolloutMode: policy.mode,
|
|
2678
|
-
decision: "bypassed",
|
|
2679
|
-
reasonCode: "not_in_rollout_sample",
|
|
2680
|
-
methodsAttempted: [],
|
|
2681
|
-
methodsApplied: [],
|
|
2682
|
-
originalTokens: 0,
|
|
2683
|
-
resultTokens: 0,
|
|
2684
|
-
savedTokens: 0,
|
|
2685
|
-
reductionPercentage: 0,
|
|
2686
|
-
compressionLatencyMs: 0,
|
|
2687
|
-
compressionComputeCostUsd: 0,
|
|
2688
|
-
financialsEstimated: true
|
|
2689
|
-
};
|
|
2690
|
-
}
|
|
2691
|
-
function failedRuntimeMeasurement(policy, latencyMs) {
|
|
2692
|
-
return {
|
|
2693
|
-
...bypassedRuntimeMeasurement(policy),
|
|
2694
|
-
decision: "fallback",
|
|
2695
|
-
reasonCode: "transformation_failed",
|
|
2696
|
-
methodsAttempted: ["deterministic"],
|
|
2697
|
-
compressionLatencyMs: latencyMs
|
|
2698
|
-
};
|
|
2699
|
-
}
|
|
2700
|
-
function anthropicRuntimeMeasurement(input) {
|
|
2701
|
-
const telemetry = input.telemetry;
|
|
2702
|
-
const originalTokens = telemetry?.originalTokens ?? estimatePromptTokens(JSON.stringify(input.originalPayload));
|
|
2703
|
-
const resultTokens = telemetry?.compressedTokens ?? originalTokens;
|
|
2704
|
-
const savedTokens = Math.max(0, telemetry?.savedTokens ?? 0);
|
|
2705
|
-
const reductionPercentage = originalTokens > 0 ? savedTokens / originalTokens * 100 : 0;
|
|
2706
|
-
const belowMinimumSize = originalTokens < input.policy.snapshot.scope.minimumTokens;
|
|
2707
|
-
const latencyExceeded = input.latencyMs > input.policy.snapshot.gates.maximumLatencyMs;
|
|
2708
|
-
const belowSavings = savedTokens < input.policy.snapshot.gates.minimumTokensRemoved || reductionPercentage < input.policy.snapshot.gates.minimumReductionPercentage;
|
|
2709
|
-
const accepted = !belowMinimumSize && !latencyExceeded && !belowSavings;
|
|
2710
|
-
const deepText = input.policy.snapshot.methods.deepText.enabled && !input.policy.snapshot.rollout.deterministicOnly && (input.policy.mode !== "CANARY" || input.policy.snapshot.rollout.deepTextCanaryAllowed);
|
|
2711
|
-
const reasonCode = belowMinimumSize ? "below_minimum_size" : latencyExceeded ? "latency_budget_exceeded" : belowSavings ? "below_minimum_savings" : void 0;
|
|
2712
|
-
const measurement = {
|
|
2713
|
-
policyId: input.policy.policyId,
|
|
2714
|
-
policyVersionId: input.policy.policyVersionId,
|
|
2715
|
-
policyVersion: input.policy.version,
|
|
2716
|
-
rolloutMode: input.policy.mode,
|
|
2717
|
-
decision: accepted ? input.shadow ? "bypassed" : "compressed" : latencyExceeded ? "fallback" : "skipped",
|
|
2718
|
-
...reasonCode ? { reasonCode } : {},
|
|
2719
|
-
methodsAttempted: ["deterministic", ...deepText ? ["deep_text"] : []],
|
|
2720
|
-
methodsApplied: accepted ? ["deterministic"] : [],
|
|
2721
|
-
originalTokens,
|
|
2722
|
-
resultTokens: accepted ? resultTokens : originalTokens,
|
|
2723
|
-
savedTokens: accepted ? savedTokens : 0,
|
|
2724
|
-
reductionPercentage: accepted ? reductionPercentage : 0,
|
|
2725
|
-
compressionLatencyMs: input.latencyMs,
|
|
2726
|
-
compressionComputeCostUsd: 0,
|
|
2727
|
-
financialsEstimated: true
|
|
2728
|
-
};
|
|
2729
|
-
return measurement;
|
|
2730
|
-
}
|
|
2731
2697
|
async function recordCompressionOutcome(args) {
|
|
2732
2698
|
const telemetry = buildPromptCompressionTelemetry(args.outcome.segments);
|
|
2733
2699
|
if (!telemetry) {
|
|
@@ -3170,10 +3136,6 @@ function resolveBeginRequest(defaults, override) {
|
|
|
3170
3136
|
}
|
|
3171
3137
|
const tags = mergeTags(base.tags, current.tags);
|
|
3172
3138
|
const begin = { customerId };
|
|
3173
|
-
const runtimeCompressionContext = current.runtimeCompressionContext ?? base.runtimeCompressionContext;
|
|
3174
|
-
if (runtimeCompressionContext) {
|
|
3175
|
-
begin.runtimeCompressionContext = runtimeCompressionContext;
|
|
3176
|
-
}
|
|
3177
3139
|
const requested = current.requested ?? base.requested;
|
|
3178
3140
|
if (requested) begin.requested = requested;
|
|
3179
3141
|
const feature = current.feature ?? base.feature;
|
|
@@ -3196,8 +3158,6 @@ function resolveBeginRequest(defaults, override) {
|
|
|
3196
3158
|
if (customerUserEmail) begin.customerUserEmail = customerUserEmail;
|
|
3197
3159
|
const stripeCustomerId = current.stripeCustomerId ?? base.stripeCustomerId;
|
|
3198
3160
|
if (stripeCustomerId) begin.stripeCustomerId = stripeCustomerId;
|
|
3199
|
-
const holdUsd = current.holdUsd ?? base.holdUsd;
|
|
3200
|
-
if (typeof holdUsd === "number") begin.holdUsd = holdUsd;
|
|
3201
3161
|
const batch = current.batch ?? base.batch;
|
|
3202
3162
|
if (typeof batch === "boolean") begin.batch = batch;
|
|
3203
3163
|
const pricingMode = current.pricingMode ?? base.pricingMode;
|
|
@@ -3333,21 +3293,21 @@ function applyAnthropicUsageRecord(usage, usageRecord) {
|
|
|
3333
3293
|
if (cacheWriteInputTokens !== void 0) {
|
|
3334
3294
|
usage.cacheWriteInputTokens = cacheWriteInputTokens;
|
|
3335
3295
|
}
|
|
3296
|
+
if (isObjectRecord(usageRecord.cache_creation)) {
|
|
3297
|
+
const cacheWrite5m = readNumber(
|
|
3298
|
+
usageRecord.cache_creation.ephemeral_5m_input_tokens
|
|
3299
|
+
);
|
|
3300
|
+
const cacheWrite1h = readNumber(
|
|
3301
|
+
usageRecord.cache_creation.ephemeral_1h_input_tokens
|
|
3302
|
+
);
|
|
3303
|
+
if (cacheWrite5m !== void 0) usage.cacheWrite5mInputTokens = cacheWrite5m;
|
|
3304
|
+
if (cacheWrite1h !== void 0) usage.cacheWrite1hInputTokens = cacheWrite1h;
|
|
3305
|
+
}
|
|
3336
3306
|
const baseInputTokens = readNumber(usageRecord.input_tokens ?? usageRecord.prompt_tokens);
|
|
3337
3307
|
if (baseInputTokens !== void 0) {
|
|
3338
3308
|
usage.inputTokens = baseInputTokens + (cachedInputTokens ?? 0) + (cacheWriteInputTokens ?? 0);
|
|
3339
3309
|
}
|
|
3340
3310
|
}
|
|
3341
|
-
function withRuntimeCompressionContext(begin, provider, model) {
|
|
3342
|
-
return {
|
|
3343
|
-
...begin,
|
|
3344
|
-
runtimeCompressionContext: {
|
|
3345
|
-
...begin.runtimeCompressionContext ?? {},
|
|
3346
|
-
provider,
|
|
3347
|
-
model
|
|
3348
|
-
}
|
|
3349
|
-
};
|
|
3350
|
-
}
|
|
3351
3311
|
function accumulateAnthropicStreamUsage(chunk, fallbackModel, state) {
|
|
3352
3312
|
const usage = extractAnthropicUsage(chunk, fallbackModel);
|
|
3353
3313
|
if (usage) {
|