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