@usagetap/sdk 1.3.1 → 1.4.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 +1058 -863
- package/dist/adapters/anthropic.cjs +990 -24
- package/dist/adapters/anthropic.cjs.map +1 -1
- package/dist/adapters/anthropic.d.cts +45 -3
- package/dist/adapters/anthropic.d.ts +45 -3
- package/dist/adapters/anthropic.mjs +990 -25
- package/dist/adapters/anthropic.mjs.map +1 -1
- package/dist/adapters/openai.cjs +1164 -44
- package/dist/adapters/openai.cjs.map +1 -1
- package/dist/adapters/openai.d.cts +46 -3
- package/dist/adapters/openai.d.ts +46 -3
- package/dist/adapters/openai.mjs +1164 -45
- package/dist/adapters/openai.mjs.map +1 -1
- package/dist/adapters/openrouter.cjs +3899 -22
- package/dist/adapters/openrouter.cjs.map +1 -1
- package/dist/adapters/openrouter.d.cts +6 -3
- package/dist/adapters/openrouter.d.ts +6 -3
- package/dist/adapters/openrouter.mjs +3897 -23
- package/dist/adapters/openrouter.mjs.map +1 -1
- package/dist/anthropic/index.cjs +990 -24
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.d.cts +2 -2
- package/dist/anthropic/index.d.ts +2 -2
- package/dist/anthropic/index.mjs +990 -25
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/client-CExQ8e1T.d.cts +1225 -0
- package/dist/client-CExQ8e1T.d.ts +1225 -0
- package/dist/express/index.cjs +421 -29
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +2 -2
- package/dist/express/index.d.ts +2 -2
- package/dist/express/index.mjs +421 -29
- package/dist/express/index.mjs.map +1 -1
- package/dist/index.cjs +680 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +680 -15
- package/dist/index.mjs.map +1 -1
- package/dist/openai/index.cjs +1165 -45
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.d.cts +2 -2
- package/dist/openai/index.d.ts +2 -2
- package/dist/openai/index.mjs +1165 -46
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openrouter/index.cjs +1182 -47
- package/dist/openrouter/index.cjs.map +1 -1
- package/dist/openrouter/index.d.cts +3 -3
- package/dist/openrouter/index.d.ts +3 -3
- package/dist/openrouter/index.mjs +1180 -46
- package/dist/openrouter/index.mjs.map +1 -1
- package/dist/react/index.cjs +19 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +17 -4
- package/dist/react/index.d.ts +17 -4
- package/dist/react/index.mjs +19 -1
- package/dist/react/index.mjs.map +1 -1
- package/package.json +84 -84
- package/dist/client-BD8O2J8Z.d.cts +0 -668
- package/dist/client-BD8O2J8Z.d.ts +0 -668
package/dist/express/index.cjs
CHANGED
|
@@ -176,6 +176,75 @@ async function pipeToResponse(stream, res, options = {}) {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
var USAGETAP_CORRELATION_HEADER = "x-usage-correlation-id";
|
|
179
|
+
function readString(value) {
|
|
180
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
181
|
+
}
|
|
182
|
+
function serializeSamplingError(error) {
|
|
183
|
+
if (error instanceof Error) {
|
|
184
|
+
return { name: error.name, message: error.message };
|
|
185
|
+
}
|
|
186
|
+
return { message: String(error) };
|
|
187
|
+
}
|
|
188
|
+
function normalizeMeteredOpenAISampling(options) {
|
|
189
|
+
if (!options) return void 0;
|
|
190
|
+
if (options === true) return { provider: "openai" };
|
|
191
|
+
const { provider = "openai", ...policyFields } = options;
|
|
192
|
+
return {
|
|
193
|
+
provider,
|
|
194
|
+
policy: typeof policyFields.rate === "number" ? policyFields : void 0
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function startMeteredOpenAISampleDecision({
|
|
198
|
+
usageTap,
|
|
199
|
+
sampling,
|
|
200
|
+
beginRequest,
|
|
201
|
+
input
|
|
202
|
+
}) {
|
|
203
|
+
if (!sampling) return Promise.resolve(false);
|
|
204
|
+
return usageTap.shouldSampleAsync(
|
|
205
|
+
{
|
|
206
|
+
customerId: beginRequest.customerId,
|
|
207
|
+
feature: beginRequest.feature,
|
|
208
|
+
input
|
|
209
|
+
},
|
|
210
|
+
sampling.policy
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
async function captureMeteredOpenAISample({
|
|
214
|
+
usageTap,
|
|
215
|
+
sampling,
|
|
216
|
+
decision,
|
|
217
|
+
ctx,
|
|
218
|
+
beginRequest,
|
|
219
|
+
input,
|
|
220
|
+
response,
|
|
221
|
+
error,
|
|
222
|
+
startedAt
|
|
223
|
+
}) {
|
|
224
|
+
if (!sampling) return;
|
|
225
|
+
let selected = false;
|
|
226
|
+
try {
|
|
227
|
+
selected = await decision;
|
|
228
|
+
} catch {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (!selected) return;
|
|
232
|
+
const record = isObjectRecord(response) ? response : {};
|
|
233
|
+
await usageTap.captureSample({
|
|
234
|
+
sampleId: ctx.begin.data.callId,
|
|
235
|
+
callId: ctx.begin.data.callId,
|
|
236
|
+
customerId: beginRequest.customerId,
|
|
237
|
+
feature: beginRequest.feature,
|
|
238
|
+
tags: beginRequest.tags,
|
|
239
|
+
provider: sampling.provider,
|
|
240
|
+
model: readString(record.model) ?? readString(input.model),
|
|
241
|
+
input,
|
|
242
|
+
...response === void 0 ? {} : { output: response },
|
|
243
|
+
usage: record.usage,
|
|
244
|
+
latencyMs: Date.now() - startedAt,
|
|
245
|
+
...error === void 0 ? {} : { error: serializeSamplingError(error) }
|
|
246
|
+
}).catch(() => void 0);
|
|
247
|
+
}
|
|
179
248
|
function wrapOpenAI(client, usageTap, options = {}) {
|
|
180
249
|
if (!client) {
|
|
181
250
|
throw new UsageTapError("USAGETAP_BAD_REQUEST", "wrapOpenAI requires an OpenAI client instance");
|
|
@@ -183,6 +252,8 @@ function wrapOpenAI(client, usageTap, options = {}) {
|
|
|
183
252
|
const defaultContext = options.defaultContext;
|
|
184
253
|
const applyVendorHints = options.applyVendorHints !== false;
|
|
185
254
|
const defaultPromptCompression = normalizePromptCompressionOptions(options.promptCompression);
|
|
255
|
+
const defaultSampling = normalizeMeteredOpenAISampling(options.sampling);
|
|
256
|
+
const provider = options.provider ?? "openai";
|
|
186
257
|
const promptCompressionStats = new OpenAIPromptCompressionStats();
|
|
187
258
|
const proxiedChat = client.chat ? createChatProxy(
|
|
188
259
|
client.chat,
|
|
@@ -190,7 +261,9 @@ function wrapOpenAI(client, usageTap, options = {}) {
|
|
|
190
261
|
defaultContext,
|
|
191
262
|
applyVendorHints,
|
|
192
263
|
defaultPromptCompression,
|
|
193
|
-
promptCompressionStats
|
|
264
|
+
promptCompressionStats,
|
|
265
|
+
defaultSampling,
|
|
266
|
+
provider
|
|
194
267
|
) : void 0;
|
|
195
268
|
const proxiedResponses = typeof client.responses !== "undefined" ? createResponsesProxy(
|
|
196
269
|
client.responses,
|
|
@@ -198,7 +271,9 @@ function wrapOpenAI(client, usageTap, options = {}) {
|
|
|
198
271
|
defaultContext,
|
|
199
272
|
applyVendorHints,
|
|
200
273
|
defaultPromptCompression,
|
|
201
|
-
promptCompressionStats
|
|
274
|
+
promptCompressionStats,
|
|
275
|
+
defaultSampling,
|
|
276
|
+
provider
|
|
202
277
|
) : void 0;
|
|
203
278
|
const handler = {
|
|
204
279
|
get(target, prop, receiver) {
|
|
@@ -225,14 +300,16 @@ function wrapOpenAI(client, usageTap, options = {}) {
|
|
|
225
300
|
};
|
|
226
301
|
return new Proxy(client, handler);
|
|
227
302
|
}
|
|
228
|
-
function createChatProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats) {
|
|
303
|
+
function createChatProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats, defaultSampling, provider) {
|
|
229
304
|
const completions = createChatCompletionsProxy(
|
|
230
305
|
resource.completions,
|
|
231
306
|
usageTap,
|
|
232
307
|
defaultContext,
|
|
233
308
|
applyVendorHints,
|
|
234
309
|
defaultPromptCompression,
|
|
235
|
-
promptCompressionStats
|
|
310
|
+
promptCompressionStats,
|
|
311
|
+
defaultSampling,
|
|
312
|
+
provider
|
|
236
313
|
);
|
|
237
314
|
const handler = {
|
|
238
315
|
get(target, prop, receiver) {
|
|
@@ -244,7 +321,7 @@ function createChatProxy(resource, usageTap, defaultContext, applyVendorHints, d
|
|
|
244
321
|
};
|
|
245
322
|
return new Proxy(resource, handler);
|
|
246
323
|
}
|
|
247
|
-
function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats) {
|
|
324
|
+
function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats, defaultSampling, provider) {
|
|
248
325
|
if (!resource || typeof resource !== "object") {
|
|
249
326
|
return void 0;
|
|
250
327
|
}
|
|
@@ -259,9 +336,20 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
259
336
|
withUsage: withUsage2,
|
|
260
337
|
promptCompression
|
|
261
338
|
} = splitUsageOptions(options);
|
|
262
|
-
const beginRequest =
|
|
339
|
+
const beginRequest = withRuntimeCompressionContext(
|
|
340
|
+
resolveBeginRequest(defaultContext, usageContext),
|
|
341
|
+
"openai",
|
|
342
|
+
String(params.model)
|
|
343
|
+
);
|
|
263
344
|
const wantsStream = isStreamingRequest(params);
|
|
264
345
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
346
|
+
const sampleStartedAt = Date.now();
|
|
347
|
+
const sampleDecision = wantsStream ? Promise.resolve(false) : startMeteredOpenAISampleDecision({
|
|
348
|
+
usageTap,
|
|
349
|
+
sampling: defaultSampling,
|
|
350
|
+
beginRequest,
|
|
351
|
+
input: params
|
|
352
|
+
});
|
|
265
353
|
const hintedParams = applyVendorHints ? applyResponsesVendorHints(params, ctx.begin.data.vendorHints) : params;
|
|
266
354
|
const finalParams = await compressResponsesParamsForCall({
|
|
267
355
|
params: hintedParams,
|
|
@@ -273,13 +361,14 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
273
361
|
withUsage: withUsage2,
|
|
274
362
|
operation: "responses.create"
|
|
275
363
|
});
|
|
364
|
+
ctx.setUsage(openAIRequestExecutionMetadata(finalParams, provider));
|
|
276
365
|
const request = attachCorrelationHeader(requestOptions, ctx.begin.correlationId);
|
|
277
366
|
if (wantsStream) {
|
|
278
367
|
const apiPromise2 = originalCreate(finalParams, request);
|
|
279
368
|
const wrappedPromise2 = transformApiPromise(apiPromise2, (rawStream) => {
|
|
280
369
|
ensureAsyncIterable(rawStream, "responses.create");
|
|
281
370
|
const wrappedStream = wrapStreamForUsageTap(rawStream, async () => {
|
|
282
|
-
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints);
|
|
371
|
+
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints, provider);
|
|
283
372
|
if (usage) {
|
|
284
373
|
ctx.setUsage(usage);
|
|
285
374
|
}
|
|
@@ -289,9 +378,31 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
289
378
|
return wrappedPromise2;
|
|
290
379
|
}
|
|
291
380
|
const apiPromise = originalCreate(finalParams, request);
|
|
292
|
-
const wrappedPromise = transformApiPromise(apiPromise, (response) => {
|
|
293
|
-
tryInferUsage(response, ctx.begin.data.vendorHints, void 0, ctx);
|
|
381
|
+
const wrappedPromise = transformApiPromise(apiPromise, async (response) => {
|
|
382
|
+
tryInferUsage(response, ctx.begin.data.vendorHints, void 0, ctx, provider);
|
|
383
|
+
await captureMeteredOpenAISample({
|
|
384
|
+
usageTap,
|
|
385
|
+
sampling: defaultSampling,
|
|
386
|
+
decision: sampleDecision,
|
|
387
|
+
ctx,
|
|
388
|
+
beginRequest,
|
|
389
|
+
input: params,
|
|
390
|
+
response,
|
|
391
|
+
startedAt: sampleStartedAt
|
|
392
|
+
});
|
|
294
393
|
return response;
|
|
394
|
+
}, async (error) => {
|
|
395
|
+
await captureMeteredOpenAISample({
|
|
396
|
+
usageTap,
|
|
397
|
+
sampling: defaultSampling,
|
|
398
|
+
decision: sampleDecision,
|
|
399
|
+
ctx,
|
|
400
|
+
beginRequest,
|
|
401
|
+
input: params,
|
|
402
|
+
error,
|
|
403
|
+
startedAt: sampleStartedAt
|
|
404
|
+
});
|
|
405
|
+
throw error;
|
|
295
406
|
});
|
|
296
407
|
return wrappedPromise;
|
|
297
408
|
}, withUsage2);
|
|
@@ -306,7 +417,7 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
306
417
|
};
|
|
307
418
|
return new Proxy(resource, handler);
|
|
308
419
|
}
|
|
309
|
-
function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats) {
|
|
420
|
+
function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVendorHints, defaultPromptCompression, promptCompressionStats, defaultSampling, provider) {
|
|
310
421
|
const originalCreate = resource.create.bind(resource);
|
|
311
422
|
const streamCandidate = resource.stream;
|
|
312
423
|
const originalStream = typeof streamCandidate === "function" ? streamCandidate.bind(resource) : void 0;
|
|
@@ -317,9 +428,20 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
317
428
|
withUsage: withUsage2,
|
|
318
429
|
promptCompression
|
|
319
430
|
} = splitUsageOptions(options);
|
|
320
|
-
const beginRequest =
|
|
431
|
+
const beginRequest = withRuntimeCompressionContext(
|
|
432
|
+
resolveBeginRequest(defaultContext, usageContext),
|
|
433
|
+
"openai",
|
|
434
|
+
String(params.model)
|
|
435
|
+
);
|
|
321
436
|
const wantsStream = isStreamingRequest(params);
|
|
322
437
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
438
|
+
const sampleStartedAt = Date.now();
|
|
439
|
+
const sampleDecision = wantsStream ? Promise.resolve(false) : startMeteredOpenAISampleDecision({
|
|
440
|
+
usageTap,
|
|
441
|
+
sampling: defaultSampling,
|
|
442
|
+
beginRequest,
|
|
443
|
+
input: params
|
|
444
|
+
});
|
|
323
445
|
const hintedParams = applyVendorHints ? applyChatVendorHints(params, ctx.begin.data.vendorHints) : params;
|
|
324
446
|
const finalParams = await compressChatParamsForCall({
|
|
325
447
|
params: hintedParams,
|
|
@@ -331,13 +453,14 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
331
453
|
withUsage: withUsage2,
|
|
332
454
|
operation: "chat.completions.create"
|
|
333
455
|
});
|
|
456
|
+
ctx.setUsage(openAIRequestExecutionMetadata(finalParams, provider));
|
|
334
457
|
const request = attachCorrelationHeader(requestOptions, ctx.begin.correlationId);
|
|
335
458
|
if (wantsStream) {
|
|
336
459
|
const apiPromise2 = originalCreate(finalParams, request);
|
|
337
460
|
const wrappedPromise2 = transformApiPromise(apiPromise2, (rawStream) => {
|
|
338
461
|
ensureAsyncIterable(rawStream, "chat.completions.create");
|
|
339
462
|
const wrappedStream2 = wrapStreamForUsageTap(rawStream, async () => {
|
|
340
|
-
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints);
|
|
463
|
+
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints, provider);
|
|
341
464
|
if (usage) {
|
|
342
465
|
ctx.setUsage(usage);
|
|
343
466
|
}
|
|
@@ -347,9 +470,31 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
347
470
|
return wrappedPromise2;
|
|
348
471
|
}
|
|
349
472
|
const apiPromise = originalCreate(finalParams, request);
|
|
350
|
-
const wrappedPromise = transformApiPromise(apiPromise, (response) => {
|
|
351
|
-
tryInferUsage(response, ctx.begin.data.vendorHints, void 0, ctx);
|
|
473
|
+
const wrappedPromise = transformApiPromise(apiPromise, async (response) => {
|
|
474
|
+
tryInferUsage(response, ctx.begin.data.vendorHints, void 0, ctx, provider);
|
|
475
|
+
await captureMeteredOpenAISample({
|
|
476
|
+
usageTap,
|
|
477
|
+
sampling: defaultSampling,
|
|
478
|
+
decision: sampleDecision,
|
|
479
|
+
ctx,
|
|
480
|
+
beginRequest,
|
|
481
|
+
input: params,
|
|
482
|
+
response,
|
|
483
|
+
startedAt: sampleStartedAt
|
|
484
|
+
});
|
|
352
485
|
return response;
|
|
486
|
+
}, async (error) => {
|
|
487
|
+
await captureMeteredOpenAISample({
|
|
488
|
+
usageTap,
|
|
489
|
+
sampling: defaultSampling,
|
|
490
|
+
decision: sampleDecision,
|
|
491
|
+
ctx,
|
|
492
|
+
beginRequest,
|
|
493
|
+
input: params,
|
|
494
|
+
error,
|
|
495
|
+
startedAt: sampleStartedAt
|
|
496
|
+
});
|
|
497
|
+
throw error;
|
|
353
498
|
});
|
|
354
499
|
return wrappedPromise;
|
|
355
500
|
}, withUsage2);
|
|
@@ -361,7 +506,11 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
361
506
|
withUsage: withUsage2,
|
|
362
507
|
promptCompression
|
|
363
508
|
} = splitUsageOptions(options);
|
|
364
|
-
const beginRequest =
|
|
509
|
+
const beginRequest = withRuntimeCompressionContext(
|
|
510
|
+
resolveBeginRequest(defaultContext, usageContext),
|
|
511
|
+
"openai",
|
|
512
|
+
String(params.model)
|
|
513
|
+
);
|
|
365
514
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
366
515
|
const hintedParams = applyVendorHints ? applyChatVendorHints(params, ctx.begin.data.vendorHints) : params;
|
|
367
516
|
const finalParams = await compressChatParamsForCall({
|
|
@@ -374,12 +523,17 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
374
523
|
withUsage: withUsage2,
|
|
375
524
|
operation: "chat.completions.stream"
|
|
376
525
|
});
|
|
526
|
+
ctx.setUsage(openAIRequestExecutionMetadata(finalParams, provider));
|
|
377
527
|
const request = attachCorrelationHeader(requestOptions, ctx.begin.correlationId);
|
|
378
528
|
const apiPromise = originalStream(finalParams, request);
|
|
379
529
|
const wrappedPromise = transformApiPromise(apiPromise, (rawStream) => {
|
|
380
530
|
ensureAsyncIterable(rawStream, "chat.completions.stream");
|
|
381
531
|
const wrappedStreamInner = wrapStreamForUsageTap(rawStream, async () => {
|
|
382
|
-
const usage = await extractUsageFromStream(
|
|
532
|
+
const usage = await extractUsageFromStream(
|
|
533
|
+
rawStream,
|
|
534
|
+
ctx.begin.data.vendorHints,
|
|
535
|
+
provider
|
|
536
|
+
);
|
|
383
537
|
if (usage) {
|
|
384
538
|
ctx.setUsage(usage);
|
|
385
539
|
}
|
|
@@ -403,19 +557,70 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
403
557
|
return new Proxy(resource, handler);
|
|
404
558
|
}
|
|
405
559
|
async function compressChatParamsForCall(args) {
|
|
406
|
-
|
|
560
|
+
let compression = resolveEffectivePromptCompressionOptions(
|
|
407
561
|
args.defaultPromptCompression,
|
|
408
562
|
args.callPromptCompression
|
|
409
563
|
);
|
|
564
|
+
const runtimePolicy = args.ctx.begin.data.runtimeCompressionPolicy;
|
|
565
|
+
const policyDriven = !compression && Boolean(runtimePolicy);
|
|
566
|
+
if (policyDriven && runtimePolicy) {
|
|
567
|
+
if (!runtimePolicy.selected) {
|
|
568
|
+
args.ctx.setUsage({
|
|
569
|
+
runtimeCompression: bypassedRuntimeMeasurement(runtimePolicy)
|
|
570
|
+
});
|
|
571
|
+
return args.params;
|
|
572
|
+
}
|
|
573
|
+
compression = openAIPolicyCompressionOptions(runtimePolicy);
|
|
574
|
+
if (runtimePolicy.mode === "SHADOW") {
|
|
575
|
+
const startedAt2 = Date.now();
|
|
576
|
+
void compressChatParams(
|
|
577
|
+
args.params,
|
|
578
|
+
args.usageTap,
|
|
579
|
+
compression,
|
|
580
|
+
args.withUsage?.signal
|
|
581
|
+
).then((outcome2) => {
|
|
582
|
+
args.ctx.setUsage({
|
|
583
|
+
runtimeCompression: openAIRuntimeMeasurement({
|
|
584
|
+
policy: runtimePolicy,
|
|
585
|
+
telemetry: buildPromptCompressionTelemetry(outcome2.segments),
|
|
586
|
+
latencyMs: Date.now() - startedAt2,
|
|
587
|
+
shadow: true,
|
|
588
|
+
originalPayload: args.params,
|
|
589
|
+
resultPayload: outcome2.params
|
|
590
|
+
})
|
|
591
|
+
});
|
|
592
|
+
}).catch(() => {
|
|
593
|
+
args.ctx.setUsage({
|
|
594
|
+
runtimeCompression: failedRuntimeMeasurement(
|
|
595
|
+
runtimePolicy,
|
|
596
|
+
Date.now() - startedAt2
|
|
597
|
+
)
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
return args.params;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
410
603
|
if (!compression) {
|
|
411
604
|
return args.params;
|
|
412
605
|
}
|
|
606
|
+
const startedAt = Date.now();
|
|
413
607
|
const outcome = await compressChatParams(
|
|
414
608
|
args.params,
|
|
415
609
|
args.usageTap,
|
|
416
610
|
compression,
|
|
417
611
|
args.withUsage?.signal
|
|
418
612
|
);
|
|
613
|
+
if (policyDriven && runtimePolicy) {
|
|
614
|
+
const runtimeMeasurement = openAIRuntimeMeasurement({
|
|
615
|
+
policy: runtimePolicy,
|
|
616
|
+
telemetry: buildPromptCompressionTelemetry(outcome.segments),
|
|
617
|
+
latencyMs: Date.now() - startedAt,
|
|
618
|
+
originalPayload: args.params,
|
|
619
|
+
resultPayload: outcome.params
|
|
620
|
+
});
|
|
621
|
+
args.ctx.setUsage({ runtimeCompression: runtimeMeasurement });
|
|
622
|
+
if (runtimeMeasurement.decision !== "compressed") return args.params;
|
|
623
|
+
}
|
|
419
624
|
await recordCompressionOutcome({
|
|
420
625
|
outcome,
|
|
421
626
|
compression,
|
|
@@ -428,19 +633,70 @@ async function compressChatParamsForCall(args) {
|
|
|
428
633
|
return outcome.params;
|
|
429
634
|
}
|
|
430
635
|
async function compressResponsesParamsForCall(args) {
|
|
431
|
-
|
|
636
|
+
let compression = resolveEffectivePromptCompressionOptions(
|
|
432
637
|
args.defaultPromptCompression,
|
|
433
638
|
args.callPromptCompression
|
|
434
639
|
);
|
|
640
|
+
const runtimePolicy = args.ctx.begin.data.runtimeCompressionPolicy;
|
|
641
|
+
const policyDriven = !compression && Boolean(runtimePolicy);
|
|
642
|
+
if (policyDriven && runtimePolicy) {
|
|
643
|
+
if (!runtimePolicy.selected) {
|
|
644
|
+
args.ctx.setUsage({
|
|
645
|
+
runtimeCompression: bypassedRuntimeMeasurement(runtimePolicy)
|
|
646
|
+
});
|
|
647
|
+
return args.params;
|
|
648
|
+
}
|
|
649
|
+
compression = openAIPolicyCompressionOptions(runtimePolicy);
|
|
650
|
+
if (runtimePolicy.mode === "SHADOW") {
|
|
651
|
+
const startedAt2 = Date.now();
|
|
652
|
+
void compressResponsesParams(
|
|
653
|
+
args.params,
|
|
654
|
+
args.usageTap,
|
|
655
|
+
compression,
|
|
656
|
+
args.withUsage?.signal
|
|
657
|
+
).then((outcome2) => {
|
|
658
|
+
args.ctx.setUsage({
|
|
659
|
+
runtimeCompression: openAIRuntimeMeasurement({
|
|
660
|
+
policy: runtimePolicy,
|
|
661
|
+
telemetry: buildPromptCompressionTelemetry(outcome2.segments),
|
|
662
|
+
latencyMs: Date.now() - startedAt2,
|
|
663
|
+
shadow: true,
|
|
664
|
+
originalPayload: args.params,
|
|
665
|
+
resultPayload: outcome2.params
|
|
666
|
+
})
|
|
667
|
+
});
|
|
668
|
+
}).catch(() => {
|
|
669
|
+
args.ctx.setUsage({
|
|
670
|
+
runtimeCompression: failedRuntimeMeasurement(
|
|
671
|
+
runtimePolicy,
|
|
672
|
+
Date.now() - startedAt2
|
|
673
|
+
)
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
return args.params;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
435
679
|
if (!compression) {
|
|
436
680
|
return args.params;
|
|
437
681
|
}
|
|
682
|
+
const startedAt = Date.now();
|
|
438
683
|
const outcome = await compressResponsesParams(
|
|
439
684
|
args.params,
|
|
440
685
|
args.usageTap,
|
|
441
686
|
compression,
|
|
442
687
|
args.withUsage?.signal
|
|
443
688
|
);
|
|
689
|
+
if (policyDriven && runtimePolicy) {
|
|
690
|
+
const runtimeMeasurement = openAIRuntimeMeasurement({
|
|
691
|
+
policy: runtimePolicy,
|
|
692
|
+
telemetry: buildPromptCompressionTelemetry(outcome.segments),
|
|
693
|
+
latencyMs: Date.now() - startedAt,
|
|
694
|
+
originalPayload: args.params,
|
|
695
|
+
resultPayload: outcome.params
|
|
696
|
+
});
|
|
697
|
+
args.ctx.setUsage({ runtimeCompression: runtimeMeasurement });
|
|
698
|
+
if (runtimeMeasurement.decision !== "compressed") return args.params;
|
|
699
|
+
}
|
|
444
700
|
await recordCompressionOutcome({
|
|
445
701
|
outcome,
|
|
446
702
|
compression,
|
|
@@ -452,6 +708,79 @@ async function compressResponsesParamsForCall(args) {
|
|
|
452
708
|
});
|
|
453
709
|
return outcome.params;
|
|
454
710
|
}
|
|
711
|
+
function openAIPolicyCompressionOptions(policy) {
|
|
712
|
+
const roles = Object.fromEntries(
|
|
713
|
+
["system", "user", "tool", "assistant"].filter((role) => policy.snapshot.scope.messageRoles.includes(role)).map((role) => [role, true])
|
|
714
|
+
);
|
|
715
|
+
return {
|
|
716
|
+
provider: "usagetap",
|
|
717
|
+
roles,
|
|
718
|
+
minContextTokens: policy.snapshot.scope.minimumTokens,
|
|
719
|
+
failOpen: true
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
function bypassedRuntimeMeasurement(policy) {
|
|
723
|
+
return {
|
|
724
|
+
policyId: policy.policyId,
|
|
725
|
+
policyVersionId: policy.policyVersionId,
|
|
726
|
+
policyVersion: policy.version,
|
|
727
|
+
rolloutMode: policy.mode,
|
|
728
|
+
decision: "bypassed",
|
|
729
|
+
reasonCode: "not_in_rollout_sample",
|
|
730
|
+
methodsAttempted: [],
|
|
731
|
+
methodsApplied: [],
|
|
732
|
+
originalTokens: 0,
|
|
733
|
+
resultTokens: 0,
|
|
734
|
+
savedTokens: 0,
|
|
735
|
+
reductionPercentage: 0,
|
|
736
|
+
compressionLatencyMs: 0,
|
|
737
|
+
compressionComputeCostUsd: 0,
|
|
738
|
+
financialsEstimated: true
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function failedRuntimeMeasurement(policy, latencyMs) {
|
|
742
|
+
return {
|
|
743
|
+
...bypassedRuntimeMeasurement(policy),
|
|
744
|
+
decision: "fallback",
|
|
745
|
+
reasonCode: "transformation_failed",
|
|
746
|
+
methodsAttempted: ["deterministic"],
|
|
747
|
+
compressionLatencyMs: latencyMs
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function openAIRuntimeMeasurement(input) {
|
|
751
|
+
const telemetry = input.telemetry;
|
|
752
|
+
const originalTokens = telemetry?.originalTokens ?? estimatePromptTokens(JSON.stringify(input.originalPayload));
|
|
753
|
+
const resultTokens = telemetry?.compressedTokens ?? originalTokens;
|
|
754
|
+
const savedTokens = Math.max(0, telemetry?.savedTokens ?? 0);
|
|
755
|
+
const reductionPercentage = originalTokens > 0 ? savedTokens / originalTokens * 100 : 0;
|
|
756
|
+
const belowMinimumSize = originalTokens < input.policy.snapshot.scope.minimumTokens;
|
|
757
|
+
const latencyExceeded = input.latencyMs > input.policy.snapshot.gates.maximumLatencyMs;
|
|
758
|
+
const belowSavings = savedTokens < input.policy.snapshot.gates.minimumTokensRemoved || reductionPercentage < input.policy.snapshot.gates.minimumReductionPercentage;
|
|
759
|
+
const accepted = !belowMinimumSize && !latencyExceeded && !belowSavings;
|
|
760
|
+
const deepText = input.policy.snapshot.methods.deepText.enabled && !input.policy.snapshot.rollout.deterministicOnly && (input.policy.mode !== "CANARY" || input.policy.snapshot.rollout.deepTextCanaryAllowed);
|
|
761
|
+
const reasonCode = belowMinimumSize ? "below_minimum_size" : latencyExceeded ? "latency_budget_exceeded" : belowSavings ? "below_minimum_savings" : void 0;
|
|
762
|
+
const measurement = {
|
|
763
|
+
policyId: input.policy.policyId,
|
|
764
|
+
policyVersionId: input.policy.policyVersionId,
|
|
765
|
+
policyVersion: input.policy.version,
|
|
766
|
+
rolloutMode: input.policy.mode,
|
|
767
|
+
decision: accepted ? input.shadow ? "bypassed" : "compressed" : latencyExceeded ? "fallback" : "skipped",
|
|
768
|
+
...reasonCode ? { reasonCode } : {},
|
|
769
|
+
methodsAttempted: [
|
|
770
|
+
"deterministic",
|
|
771
|
+
...deepText ? ["deep_text"] : []
|
|
772
|
+
],
|
|
773
|
+
methodsApplied: accepted ? ["deterministic"] : [],
|
|
774
|
+
originalTokens,
|
|
775
|
+
resultTokens: accepted ? resultTokens : originalTokens,
|
|
776
|
+
savedTokens: accepted ? savedTokens : 0,
|
|
777
|
+
reductionPercentage: accepted ? reductionPercentage : 0,
|
|
778
|
+
compressionLatencyMs: input.latencyMs,
|
|
779
|
+
compressionComputeCostUsd: 0,
|
|
780
|
+
financialsEstimated: true
|
|
781
|
+
};
|
|
782
|
+
return measurement;
|
|
783
|
+
}
|
|
455
784
|
async function recordCompressionOutcome(args) {
|
|
456
785
|
const telemetry = buildPromptCompressionTelemetry(args.outcome.segments);
|
|
457
786
|
if (!telemetry) {
|
|
@@ -505,6 +834,10 @@ async function compressChatParams(params, usageTap, compression, signal) {
|
|
|
505
834
|
const result = await usageTap.compressPromptMessages(source, {
|
|
506
835
|
provider: "usagetap",
|
|
507
836
|
failOpen: compression.failOpen,
|
|
837
|
+
mode: compression.mode,
|
|
838
|
+
latencyBudgetMs: compression.latencyBudgetMs,
|
|
839
|
+
compactEmptyUserMessages: compression.compactEmptyUserMessages,
|
|
840
|
+
compactDuplicateUserTextParts: compression.compactDuplicateUserTextParts,
|
|
508
841
|
aggressiveness: resolveMessageEndpointAggressiveness(compression),
|
|
509
842
|
signal
|
|
510
843
|
});
|
|
@@ -970,23 +1303,53 @@ function resolveBeginRequest(defaults, override) {
|
|
|
970
1303
|
}
|
|
971
1304
|
const tags = mergeTags(base.tags, current.tags);
|
|
972
1305
|
const begin = { customerId };
|
|
1306
|
+
const runtimeCompressionContext = current.runtimeCompressionContext ?? base.runtimeCompressionContext;
|
|
1307
|
+
if (runtimeCompressionContext) {
|
|
1308
|
+
begin.runtimeCompressionContext = runtimeCompressionContext;
|
|
1309
|
+
}
|
|
973
1310
|
const requested = current.requested ?? base.requested;
|
|
974
1311
|
if (requested) begin.requested = requested;
|
|
975
1312
|
const feature = current.feature ?? base.feature;
|
|
976
1313
|
if (feature) begin.feature = feature;
|
|
1314
|
+
const runId = current.runId ?? base.runId;
|
|
1315
|
+
if (runId) begin.runId = runId;
|
|
977
1316
|
const idempotency = current.idempotency ?? base.idempotency;
|
|
978
1317
|
if (idempotency) begin.idempotency = idempotency;
|
|
979
1318
|
const customerName = current.customerName ?? base.customerName;
|
|
980
1319
|
if (customerName) begin.customerName = customerName;
|
|
981
1320
|
const customerEmail = current.customerEmail ?? base.customerEmail;
|
|
982
1321
|
if (customerEmail) begin.customerEmail = customerEmail;
|
|
1322
|
+
const customerUserId = current.customerUserId ?? base.customerUserId;
|
|
1323
|
+
if (customerUserId) begin.customerUserId = customerUserId;
|
|
1324
|
+
const customerUserName = current.customerUserName ?? base.customerUserName;
|
|
1325
|
+
if (customerUserName) begin.customerUserName = customerUserName;
|
|
1326
|
+
const customerUserEmail = current.customerUserEmail ?? base.customerUserEmail;
|
|
1327
|
+
if (customerUserEmail) begin.customerUserEmail = customerUserEmail;
|
|
1328
|
+
const stripeCustomerId = current.stripeCustomerId ?? base.stripeCustomerId;
|
|
1329
|
+
if (stripeCustomerId) begin.stripeCustomerId = stripeCustomerId;
|
|
1330
|
+
const holdUsd = current.holdUsd ?? base.holdUsd;
|
|
1331
|
+
if (typeof holdUsd === "number") begin.holdUsd = holdUsd;
|
|
1332
|
+
const batch = current.batch ?? base.batch;
|
|
1333
|
+
if (typeof batch === "boolean") begin.batch = batch;
|
|
1334
|
+
const pricingMode = current.pricingMode ?? base.pricingMode;
|
|
1335
|
+
if (pricingMode) begin.pricingMode = pricingMode;
|
|
983
1336
|
if (tags?.length) {
|
|
984
1337
|
begin.tags = tags;
|
|
985
1338
|
}
|
|
986
1339
|
return begin;
|
|
987
1340
|
}
|
|
988
|
-
function
|
|
989
|
-
|
|
1341
|
+
function withRuntimeCompressionContext(begin, provider, model) {
|
|
1342
|
+
return {
|
|
1343
|
+
...begin,
|
|
1344
|
+
runtimeCompressionContext: {
|
|
1345
|
+
...begin.runtimeCompressionContext ?? {},
|
|
1346
|
+
provider,
|
|
1347
|
+
model
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
function transformApiPromise(apiPromise, onResolve, onReject) {
|
|
1352
|
+
const resolvedPromise = Promise.resolve(apiPromise).then(onResolve, onReject);
|
|
990
1353
|
if (isObjectRecord(apiPromise)) {
|
|
991
1354
|
const proto = Object.getPrototypeOf(apiPromise);
|
|
992
1355
|
if (proto) {
|
|
@@ -1121,12 +1484,12 @@ function applyResponsesVendorHints(params, hints) {
|
|
|
1121
1484
|
}
|
|
1122
1485
|
return next;
|
|
1123
1486
|
}
|
|
1124
|
-
async function extractUsageFromStream(stream, hints) {
|
|
1487
|
+
async function extractUsageFromStream(stream, hints, provider = "openai") {
|
|
1125
1488
|
const finalPayload = await resolveStreamFinalPayload(stream);
|
|
1126
1489
|
if (!finalPayload) {
|
|
1127
1490
|
return void 0;
|
|
1128
1491
|
}
|
|
1129
|
-
return inferUsageFromResponse(finalPayload, hints);
|
|
1492
|
+
return inferUsageFromResponse(finalPayload, hints, provider);
|
|
1130
1493
|
}
|
|
1131
1494
|
async function resolveStreamFinalPayload(stream) {
|
|
1132
1495
|
if (!stream || typeof stream !== "object") {
|
|
@@ -1199,13 +1562,13 @@ function setHeaderIfPossible(res, key, value) {
|
|
|
1199
1562
|
res.setHeader(key, value);
|
|
1200
1563
|
}
|
|
1201
1564
|
}
|
|
1202
|
-
function tryInferUsage(response, hints, extractor, ctx) {
|
|
1203
|
-
const inferred = inferUsageFromResponse(response, hints);
|
|
1565
|
+
function tryInferUsage(response, hints, extractor, ctx, provider = "openai") {
|
|
1566
|
+
const inferred = inferUsageFromResponse(response, hints, provider);
|
|
1204
1567
|
if (inferred) {
|
|
1205
1568
|
ctx.setUsage(inferred);
|
|
1206
1569
|
}
|
|
1207
1570
|
}
|
|
1208
|
-
function inferUsageFromResponse(response, hints) {
|
|
1571
|
+
function inferUsageFromResponse(response, hints, provider = "openai") {
|
|
1209
1572
|
if (!response || typeof response !== "object") {
|
|
1210
1573
|
return void 0;
|
|
1211
1574
|
}
|
|
@@ -1213,12 +1576,41 @@ function inferUsageFromResponse(response, hints) {
|
|
|
1213
1576
|
if (!candidate.usage) {
|
|
1214
1577
|
return void 0;
|
|
1215
1578
|
}
|
|
1216
|
-
const cachedInputTokens = candidate.usage.prompt_tokens_details?.cached_tokens ?? candidate.usage.cached_tokens;
|
|
1579
|
+
const cachedInputTokens = candidate.usage.prompt_tokens_details?.cached_tokens ?? candidate.usage.input_tokens_details?.cached_tokens ?? candidate.usage.cached_tokens;
|
|
1580
|
+
const responseEffort = normalizeExecutionReasoningEffort(
|
|
1581
|
+
candidate.reasoning?.effort
|
|
1582
|
+
);
|
|
1217
1583
|
return {
|
|
1584
|
+
providerUsed: provider,
|
|
1218
1585
|
modelUsed: candidate.model ?? hints?.preferredModel,
|
|
1219
|
-
inputTokens: candidate.usage.prompt_tokens,
|
|
1220
|
-
responseTokens: candidate.usage.completion_tokens,
|
|
1221
|
-
cachedInputTokens
|
|
1586
|
+
inputTokens: candidate.usage.prompt_tokens ?? candidate.usage.input_tokens,
|
|
1587
|
+
responseTokens: candidate.usage.completion_tokens ?? candidate.usage.output_tokens,
|
|
1588
|
+
cachedInputTokens,
|
|
1589
|
+
reasoningTokens: candidate.usage.completion_tokens_details?.reasoning_tokens ?? candidate.usage.output_tokens_details?.reasoning_tokens,
|
|
1590
|
+
...responseEffort ? {
|
|
1591
|
+
reasoningEffort: responseEffort,
|
|
1592
|
+
reasoningEffortSource: "provider_response"
|
|
1593
|
+
} : {},
|
|
1594
|
+
...typeof candidate.reasoning?.type === "string" ? { reasoningMode: candidate.reasoning.type } : typeof candidate.reasoning?.mode === "string" ? { reasoningMode: candidate.reasoning.mode } : {}
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
function normalizeExecutionReasoningEffort(value) {
|
|
1598
|
+
return value === "none" || value === "minimal" || value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max" ? value : void 0;
|
|
1599
|
+
}
|
|
1600
|
+
function openAIRequestExecutionMetadata(params, provider) {
|
|
1601
|
+
const record = params && typeof params === "object" ? params : {};
|
|
1602
|
+
const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
|
|
1603
|
+
const effort = normalizeExecutionReasoningEffort(
|
|
1604
|
+
record.reasoning_effort ?? reasoning?.effort ?? record.thinking_level
|
|
1605
|
+
);
|
|
1606
|
+
const mode = typeof reasoning?.type === "string" ? reasoning.type : typeof reasoning?.mode === "string" ? reasoning.mode : void 0;
|
|
1607
|
+
const rawBudget = reasoning?.budget_tokens ?? record.thinking_budget ?? record.thinking_budget_tokens;
|
|
1608
|
+
const budget = typeof rawBudget === "number" && Number.isInteger(rawBudget) && rawBudget >= 0 ? rawBudget : void 0;
|
|
1609
|
+
return {
|
|
1610
|
+
providerUsed: provider,
|
|
1611
|
+
...effort ? { reasoningEffort: effort, reasoningEffortSource: "provider_request" } : {},
|
|
1612
|
+
...mode ? { reasoningMode: mode } : {},
|
|
1613
|
+
...budget !== void 0 ? { reasoningBudgetTokens: budget } : {}
|
|
1222
1614
|
};
|
|
1223
1615
|
}
|
|
1224
1616
|
function wrapStreamForUsageTap(source, finalize, ctx) {
|