@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/express/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import { Request, Response, NextFunction } from 'express';
|
|
3
|
-
import { U as UsageTapClient } from '../client-
|
|
3
|
+
import { U as UsageTapClient } from '../client-C0UiaqVB.cjs';
|
|
4
4
|
import { WrapOpenAIContext, WrapOpenAIOptions, wrapOpenAI, pipeToResponse } from '../adapters/openai.cjs';
|
|
5
5
|
|
|
6
6
|
interface ExpressUsageTapContext {
|
package/dist/express/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import { Request, Response, NextFunction } from 'express';
|
|
3
|
-
import { U as UsageTapClient } from '../client-
|
|
3
|
+
import { U as UsageTapClient } from '../client-C0UiaqVB.js';
|
|
4
4
|
import { WrapOpenAIContext, WrapOpenAIOptions, wrapOpenAI, pipeToResponse } from '../adapters/openai.js';
|
|
5
5
|
|
|
6
6
|
interface ExpressUsageTapContext {
|
package/dist/express/index.mjs
CHANGED
|
@@ -334,13 +334,13 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
334
334
|
withUsage: withUsage2,
|
|
335
335
|
promptCompression
|
|
336
336
|
} = splitUsageOptions(options);
|
|
337
|
-
const beginRequest =
|
|
337
|
+
const beginRequest = responsesBeginRequest(
|
|
338
338
|
resolveBeginRequest(defaultContext, usageContext),
|
|
339
|
-
|
|
340
|
-
String(params.model)
|
|
339
|
+
params
|
|
341
340
|
);
|
|
342
341
|
const wantsStream = isStreamingRequest(params);
|
|
343
342
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
343
|
+
const settle = wantsStream ? deferUsageFinalization(ctx) : void 0;
|
|
344
344
|
const sampleStartedAt = Date.now();
|
|
345
345
|
const sampleDecision = wantsStream ? Promise.resolve(false) : startMeteredOpenAISampleDecision({
|
|
346
346
|
usageTap,
|
|
@@ -365,12 +365,31 @@ function createResponsesProxy(resource, usageTap, defaultContext, applyVendorHin
|
|
|
365
365
|
const apiPromise2 = originalCreate(finalParams, request);
|
|
366
366
|
const wrappedPromise2 = transformApiPromise(apiPromise2, (rawStream) => {
|
|
367
367
|
ensureAsyncIterable(rawStream, "responses.create");
|
|
368
|
-
const wrappedStream = wrapStreamForUsageTap(rawStream, async () => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
368
|
+
const wrappedStream = wrapStreamForUsageTap(rawStream, async (termination) => {
|
|
369
|
+
try {
|
|
370
|
+
if (termination === "complete") {
|
|
371
|
+
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints, provider);
|
|
372
|
+
if (usage) {
|
|
373
|
+
ctx.setUsage(usage);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
} catch (error) {
|
|
377
|
+
ctx.setError({
|
|
378
|
+
code: "USAGE_FINALIZE_ERROR",
|
|
379
|
+
message: error instanceof Error ? error.message : String(error)
|
|
380
|
+
});
|
|
381
|
+
throw error;
|
|
382
|
+
} finally {
|
|
383
|
+
await settle?.();
|
|
372
384
|
}
|
|
373
|
-
}, ctx)
|
|
385
|
+
}, ctx, (chunk) => {
|
|
386
|
+
tryInferUsageFromStreamChunk(
|
|
387
|
+
chunk,
|
|
388
|
+
ctx.begin.data.vendorHints,
|
|
389
|
+
ctx,
|
|
390
|
+
provider
|
|
391
|
+
);
|
|
392
|
+
});
|
|
374
393
|
return wrappedStream;
|
|
375
394
|
});
|
|
376
395
|
return wrappedPromise2;
|
|
@@ -426,13 +445,10 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
426
445
|
withUsage: withUsage2,
|
|
427
446
|
promptCompression
|
|
428
447
|
} = splitUsageOptions(options);
|
|
429
|
-
const beginRequest =
|
|
430
|
-
resolveBeginRequest(defaultContext, usageContext),
|
|
431
|
-
"openai",
|
|
432
|
-
String(params.model)
|
|
433
|
-
);
|
|
448
|
+
const beginRequest = resolveBeginRequest(defaultContext, usageContext);
|
|
434
449
|
const wantsStream = isStreamingRequest(params);
|
|
435
450
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
451
|
+
const settle = wantsStream ? deferUsageFinalization(ctx) : void 0;
|
|
436
452
|
const sampleStartedAt = Date.now();
|
|
437
453
|
const sampleDecision = wantsStream ? Promise.resolve(false) : startMeteredOpenAISampleDecision({
|
|
438
454
|
usageTap,
|
|
@@ -441,7 +457,7 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
441
457
|
input: params
|
|
442
458
|
});
|
|
443
459
|
const hintedParams = applyVendorHints ? applyChatVendorHints(params, ctx.begin.data.vendorHints) : params;
|
|
444
|
-
const
|
|
460
|
+
const compressedParams = await compressChatParamsForCall({
|
|
445
461
|
params: hintedParams,
|
|
446
462
|
usageTap,
|
|
447
463
|
ctx,
|
|
@@ -451,18 +467,38 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
451
467
|
withUsage: withUsage2,
|
|
452
468
|
operation: "chat.completions.create"
|
|
453
469
|
});
|
|
470
|
+
const finalParams = wantsStream ? ensureOpenAIStreamUsage(compressedParams) : compressedParams;
|
|
454
471
|
ctx.setUsage(openAIRequestExecutionMetadata(finalParams, provider));
|
|
455
472
|
const request = attachCorrelationHeader(requestOptions, ctx.begin.correlationId);
|
|
456
473
|
if (wantsStream) {
|
|
457
474
|
const apiPromise2 = originalCreate(finalParams, request);
|
|
458
475
|
const wrappedPromise2 = transformApiPromise(apiPromise2, (rawStream) => {
|
|
459
476
|
ensureAsyncIterable(rawStream, "chat.completions.create");
|
|
460
|
-
const wrappedStream2 = wrapStreamForUsageTap(rawStream, async () => {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
477
|
+
const wrappedStream2 = wrapStreamForUsageTap(rawStream, async (termination) => {
|
|
478
|
+
try {
|
|
479
|
+
if (termination === "complete") {
|
|
480
|
+
const usage = await extractUsageFromStream(rawStream, ctx.begin.data.vendorHints, provider);
|
|
481
|
+
if (usage) {
|
|
482
|
+
ctx.setUsage(usage);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
} catch (error) {
|
|
486
|
+
ctx.setError({
|
|
487
|
+
code: "USAGE_FINALIZE_ERROR",
|
|
488
|
+
message: error instanceof Error ? error.message : String(error)
|
|
489
|
+
});
|
|
490
|
+
throw error;
|
|
491
|
+
} finally {
|
|
492
|
+
await settle?.();
|
|
464
493
|
}
|
|
465
|
-
}, ctx)
|
|
494
|
+
}, ctx, (chunk) => {
|
|
495
|
+
tryInferUsageFromStreamChunk(
|
|
496
|
+
chunk,
|
|
497
|
+
ctx.begin.data.vendorHints,
|
|
498
|
+
ctx,
|
|
499
|
+
provider
|
|
500
|
+
);
|
|
501
|
+
});
|
|
466
502
|
return wrappedStream2;
|
|
467
503
|
});
|
|
468
504
|
return wrappedPromise2;
|
|
@@ -504,14 +540,11 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
504
540
|
withUsage: withUsage2,
|
|
505
541
|
promptCompression
|
|
506
542
|
} = splitUsageOptions(options);
|
|
507
|
-
const beginRequest =
|
|
508
|
-
resolveBeginRequest(defaultContext, usageContext),
|
|
509
|
-
"openai",
|
|
510
|
-
String(params.model)
|
|
511
|
-
);
|
|
543
|
+
const beginRequest = resolveBeginRequest(defaultContext, usageContext);
|
|
512
544
|
return usageTap.withUsage(beginRequest, async (ctx) => {
|
|
545
|
+
const settle = deferUsageFinalization(ctx);
|
|
513
546
|
const hintedParams = applyVendorHints ? applyChatVendorHints(params, ctx.begin.data.vendorHints) : params;
|
|
514
|
-
const
|
|
547
|
+
const compressedParams = await compressChatParamsForCall({
|
|
515
548
|
params: hintedParams,
|
|
516
549
|
usageTap,
|
|
517
550
|
ctx,
|
|
@@ -521,21 +554,41 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
521
554
|
withUsage: withUsage2,
|
|
522
555
|
operation: "chat.completions.stream"
|
|
523
556
|
});
|
|
557
|
+
const finalParams = ensureOpenAIStreamUsage(compressedParams);
|
|
524
558
|
ctx.setUsage(openAIRequestExecutionMetadata(finalParams, provider));
|
|
525
559
|
const request = attachCorrelationHeader(requestOptions, ctx.begin.correlationId);
|
|
526
560
|
const apiPromise = originalStream(finalParams, request);
|
|
527
561
|
const wrappedPromise = transformApiPromise(apiPromise, (rawStream) => {
|
|
528
562
|
ensureAsyncIterable(rawStream, "chat.completions.stream");
|
|
529
|
-
const wrappedStreamInner = wrapStreamForUsageTap(rawStream, async () => {
|
|
530
|
-
|
|
531
|
-
|
|
563
|
+
const wrappedStreamInner = wrapStreamForUsageTap(rawStream, async (termination) => {
|
|
564
|
+
try {
|
|
565
|
+
if (termination === "complete") {
|
|
566
|
+
const usage = await extractUsageFromStream(
|
|
567
|
+
rawStream,
|
|
568
|
+
ctx.begin.data.vendorHints,
|
|
569
|
+
provider
|
|
570
|
+
);
|
|
571
|
+
if (usage) {
|
|
572
|
+
ctx.setUsage(usage);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
} catch (error) {
|
|
576
|
+
ctx.setError({
|
|
577
|
+
code: "USAGE_FINALIZE_ERROR",
|
|
578
|
+
message: error instanceof Error ? error.message : String(error)
|
|
579
|
+
});
|
|
580
|
+
throw error;
|
|
581
|
+
} finally {
|
|
582
|
+
await settle();
|
|
583
|
+
}
|
|
584
|
+
}, ctx, (chunk) => {
|
|
585
|
+
tryInferUsageFromStreamChunk(
|
|
586
|
+
chunk,
|
|
532
587
|
ctx.begin.data.vendorHints,
|
|
588
|
+
ctx,
|
|
533
589
|
provider
|
|
534
590
|
);
|
|
535
|
-
|
|
536
|
-
ctx.setUsage(usage);
|
|
537
|
-
}
|
|
538
|
-
}, ctx);
|
|
591
|
+
});
|
|
539
592
|
return wrappedStreamInner;
|
|
540
593
|
});
|
|
541
594
|
return wrappedPromise;
|
|
@@ -555,70 +608,19 @@ function createChatCompletionsProxy(resource, usageTap, defaultContext, applyVen
|
|
|
555
608
|
return new Proxy(resource, handler);
|
|
556
609
|
}
|
|
557
610
|
async function compressChatParamsForCall(args) {
|
|
558
|
-
|
|
611
|
+
const compression = resolveEffectivePromptCompressionOptions(
|
|
559
612
|
args.defaultPromptCompression,
|
|
560
613
|
args.callPromptCompression
|
|
561
614
|
);
|
|
562
|
-
const runtimePolicy = args.ctx.begin.data.runtimeCompressionPolicy;
|
|
563
|
-
const policyDriven = !compression && Boolean(runtimePolicy);
|
|
564
|
-
if (policyDriven && runtimePolicy) {
|
|
565
|
-
if (!runtimePolicy.selected) {
|
|
566
|
-
args.ctx.setUsage({
|
|
567
|
-
runtimeCompression: bypassedRuntimeMeasurement(runtimePolicy)
|
|
568
|
-
});
|
|
569
|
-
return args.params;
|
|
570
|
-
}
|
|
571
|
-
compression = openAIPolicyCompressionOptions(runtimePolicy);
|
|
572
|
-
if (runtimePolicy.mode === "SHADOW") {
|
|
573
|
-
const startedAt2 = Date.now();
|
|
574
|
-
void compressChatParams(
|
|
575
|
-
args.params,
|
|
576
|
-
args.usageTap,
|
|
577
|
-
compression,
|
|
578
|
-
args.withUsage?.signal
|
|
579
|
-
).then((outcome2) => {
|
|
580
|
-
args.ctx.setUsage({
|
|
581
|
-
runtimeCompression: openAIRuntimeMeasurement({
|
|
582
|
-
policy: runtimePolicy,
|
|
583
|
-
telemetry: buildPromptCompressionTelemetry(outcome2.segments),
|
|
584
|
-
latencyMs: Date.now() - startedAt2,
|
|
585
|
-
shadow: true,
|
|
586
|
-
originalPayload: args.params,
|
|
587
|
-
resultPayload: outcome2.params
|
|
588
|
-
})
|
|
589
|
-
});
|
|
590
|
-
}).catch(() => {
|
|
591
|
-
args.ctx.setUsage({
|
|
592
|
-
runtimeCompression: failedRuntimeMeasurement(
|
|
593
|
-
runtimePolicy,
|
|
594
|
-
Date.now() - startedAt2
|
|
595
|
-
)
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
return args.params;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
615
|
if (!compression) {
|
|
602
616
|
return args.params;
|
|
603
617
|
}
|
|
604
|
-
const startedAt = Date.now();
|
|
605
618
|
const outcome = await compressChatParams(
|
|
606
619
|
args.params,
|
|
607
620
|
args.usageTap,
|
|
608
621
|
compression,
|
|
609
622
|
args.withUsage?.signal
|
|
610
623
|
);
|
|
611
|
-
if (policyDriven && runtimePolicy) {
|
|
612
|
-
const runtimeMeasurement = openAIRuntimeMeasurement({
|
|
613
|
-
policy: runtimePolicy,
|
|
614
|
-
telemetry: buildPromptCompressionTelemetry(outcome.segments),
|
|
615
|
-
latencyMs: Date.now() - startedAt,
|
|
616
|
-
originalPayload: args.params,
|
|
617
|
-
resultPayload: outcome.params
|
|
618
|
-
});
|
|
619
|
-
args.ctx.setUsage({ runtimeCompression: runtimeMeasurement });
|
|
620
|
-
if (runtimeMeasurement.decision !== "compressed") return args.params;
|
|
621
|
-
}
|
|
622
624
|
await recordCompressionOutcome({
|
|
623
625
|
outcome,
|
|
624
626
|
compression,
|
|
@@ -631,70 +633,19 @@ async function compressChatParamsForCall(args) {
|
|
|
631
633
|
return outcome.params;
|
|
632
634
|
}
|
|
633
635
|
async function compressResponsesParamsForCall(args) {
|
|
634
|
-
|
|
636
|
+
const compression = resolveEffectivePromptCompressionOptions(
|
|
635
637
|
args.defaultPromptCompression,
|
|
636
638
|
args.callPromptCompression
|
|
637
639
|
);
|
|
638
|
-
const runtimePolicy = args.ctx.begin.data.runtimeCompressionPolicy;
|
|
639
|
-
const policyDriven = !compression && Boolean(runtimePolicy);
|
|
640
|
-
if (policyDriven && runtimePolicy) {
|
|
641
|
-
if (!runtimePolicy.selected) {
|
|
642
|
-
args.ctx.setUsage({
|
|
643
|
-
runtimeCompression: bypassedRuntimeMeasurement(runtimePolicy)
|
|
644
|
-
});
|
|
645
|
-
return args.params;
|
|
646
|
-
}
|
|
647
|
-
compression = openAIPolicyCompressionOptions(runtimePolicy);
|
|
648
|
-
if (runtimePolicy.mode === "SHADOW") {
|
|
649
|
-
const startedAt2 = Date.now();
|
|
650
|
-
void compressResponsesParams(
|
|
651
|
-
args.params,
|
|
652
|
-
args.usageTap,
|
|
653
|
-
compression,
|
|
654
|
-
args.withUsage?.signal
|
|
655
|
-
).then((outcome2) => {
|
|
656
|
-
args.ctx.setUsage({
|
|
657
|
-
runtimeCompression: openAIRuntimeMeasurement({
|
|
658
|
-
policy: runtimePolicy,
|
|
659
|
-
telemetry: buildPromptCompressionTelemetry(outcome2.segments),
|
|
660
|
-
latencyMs: Date.now() - startedAt2,
|
|
661
|
-
shadow: true,
|
|
662
|
-
originalPayload: args.params,
|
|
663
|
-
resultPayload: outcome2.params
|
|
664
|
-
})
|
|
665
|
-
});
|
|
666
|
-
}).catch(() => {
|
|
667
|
-
args.ctx.setUsage({
|
|
668
|
-
runtimeCompression: failedRuntimeMeasurement(
|
|
669
|
-
runtimePolicy,
|
|
670
|
-
Date.now() - startedAt2
|
|
671
|
-
)
|
|
672
|
-
});
|
|
673
|
-
});
|
|
674
|
-
return args.params;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
640
|
if (!compression) {
|
|
678
641
|
return args.params;
|
|
679
642
|
}
|
|
680
|
-
const startedAt = Date.now();
|
|
681
643
|
const outcome = await compressResponsesParams(
|
|
682
644
|
args.params,
|
|
683
645
|
args.usageTap,
|
|
684
646
|
compression,
|
|
685
647
|
args.withUsage?.signal
|
|
686
648
|
);
|
|
687
|
-
if (policyDriven && runtimePolicy) {
|
|
688
|
-
const runtimeMeasurement = openAIRuntimeMeasurement({
|
|
689
|
-
policy: runtimePolicy,
|
|
690
|
-
telemetry: buildPromptCompressionTelemetry(outcome.segments),
|
|
691
|
-
latencyMs: Date.now() - startedAt,
|
|
692
|
-
originalPayload: args.params,
|
|
693
|
-
resultPayload: outcome.params
|
|
694
|
-
});
|
|
695
|
-
args.ctx.setUsage({ runtimeCompression: runtimeMeasurement });
|
|
696
|
-
if (runtimeMeasurement.decision !== "compressed") return args.params;
|
|
697
|
-
}
|
|
698
649
|
await recordCompressionOutcome({
|
|
699
650
|
outcome,
|
|
700
651
|
compression,
|
|
@@ -706,79 +657,6 @@ async function compressResponsesParamsForCall(args) {
|
|
|
706
657
|
});
|
|
707
658
|
return outcome.params;
|
|
708
659
|
}
|
|
709
|
-
function openAIPolicyCompressionOptions(policy) {
|
|
710
|
-
const roles = Object.fromEntries(
|
|
711
|
-
["system", "user", "tool", "assistant"].filter((role) => policy.snapshot.scope.messageRoles.includes(role)).map((role) => [role, true])
|
|
712
|
-
);
|
|
713
|
-
return {
|
|
714
|
-
provider: "usagetap",
|
|
715
|
-
roles,
|
|
716
|
-
minContextTokens: policy.snapshot.scope.minimumTokens,
|
|
717
|
-
failOpen: true
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
function bypassedRuntimeMeasurement(policy) {
|
|
721
|
-
return {
|
|
722
|
-
policyId: policy.policyId,
|
|
723
|
-
policyVersionId: policy.policyVersionId,
|
|
724
|
-
policyVersion: policy.version,
|
|
725
|
-
rolloutMode: policy.mode,
|
|
726
|
-
decision: "bypassed",
|
|
727
|
-
reasonCode: "not_in_rollout_sample",
|
|
728
|
-
methodsAttempted: [],
|
|
729
|
-
methodsApplied: [],
|
|
730
|
-
originalTokens: 0,
|
|
731
|
-
resultTokens: 0,
|
|
732
|
-
savedTokens: 0,
|
|
733
|
-
reductionPercentage: 0,
|
|
734
|
-
compressionLatencyMs: 0,
|
|
735
|
-
compressionComputeCostUsd: 0,
|
|
736
|
-
financialsEstimated: true
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
function failedRuntimeMeasurement(policy, latencyMs) {
|
|
740
|
-
return {
|
|
741
|
-
...bypassedRuntimeMeasurement(policy),
|
|
742
|
-
decision: "fallback",
|
|
743
|
-
reasonCode: "transformation_failed",
|
|
744
|
-
methodsAttempted: ["deterministic"],
|
|
745
|
-
compressionLatencyMs: latencyMs
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
function openAIRuntimeMeasurement(input) {
|
|
749
|
-
const telemetry = input.telemetry;
|
|
750
|
-
const originalTokens = telemetry?.originalTokens ?? estimatePromptTokens(JSON.stringify(input.originalPayload));
|
|
751
|
-
const resultTokens = telemetry?.compressedTokens ?? originalTokens;
|
|
752
|
-
const savedTokens = Math.max(0, telemetry?.savedTokens ?? 0);
|
|
753
|
-
const reductionPercentage = originalTokens > 0 ? savedTokens / originalTokens * 100 : 0;
|
|
754
|
-
const belowMinimumSize = originalTokens < input.policy.snapshot.scope.minimumTokens;
|
|
755
|
-
const latencyExceeded = input.latencyMs > input.policy.snapshot.gates.maximumLatencyMs;
|
|
756
|
-
const belowSavings = savedTokens < input.policy.snapshot.gates.minimumTokensRemoved || reductionPercentage < input.policy.snapshot.gates.minimumReductionPercentage;
|
|
757
|
-
const accepted = !belowMinimumSize && !latencyExceeded && !belowSavings;
|
|
758
|
-
const deepText = input.policy.snapshot.methods.deepText.enabled && !input.policy.snapshot.rollout.deterministicOnly && (input.policy.mode !== "CANARY" || input.policy.snapshot.rollout.deepTextCanaryAllowed);
|
|
759
|
-
const reasonCode = belowMinimumSize ? "below_minimum_size" : latencyExceeded ? "latency_budget_exceeded" : belowSavings ? "below_minimum_savings" : void 0;
|
|
760
|
-
const measurement = {
|
|
761
|
-
policyId: input.policy.policyId,
|
|
762
|
-
policyVersionId: input.policy.policyVersionId,
|
|
763
|
-
policyVersion: input.policy.version,
|
|
764
|
-
rolloutMode: input.policy.mode,
|
|
765
|
-
decision: accepted ? input.shadow ? "bypassed" : "compressed" : latencyExceeded ? "fallback" : "skipped",
|
|
766
|
-
...reasonCode ? { reasonCode } : {},
|
|
767
|
-
methodsAttempted: [
|
|
768
|
-
"deterministic",
|
|
769
|
-
...deepText ? ["deep_text"] : []
|
|
770
|
-
],
|
|
771
|
-
methodsApplied: accepted ? ["deterministic"] : [],
|
|
772
|
-
originalTokens,
|
|
773
|
-
resultTokens: accepted ? resultTokens : originalTokens,
|
|
774
|
-
savedTokens: accepted ? savedTokens : 0,
|
|
775
|
-
reductionPercentage: accepted ? reductionPercentage : 0,
|
|
776
|
-
compressionLatencyMs: input.latencyMs,
|
|
777
|
-
compressionComputeCostUsd: 0,
|
|
778
|
-
financialsEstimated: true
|
|
779
|
-
};
|
|
780
|
-
return measurement;
|
|
781
|
-
}
|
|
782
660
|
async function recordCompressionOutcome(args) {
|
|
783
661
|
const telemetry = buildPromptCompressionTelemetry(args.outcome.segments);
|
|
784
662
|
if (!telemetry) {
|
|
@@ -1301,10 +1179,6 @@ function resolveBeginRequest(defaults, override) {
|
|
|
1301
1179
|
}
|
|
1302
1180
|
const tags = mergeTags(base.tags, current.tags);
|
|
1303
1181
|
const begin = { customerId };
|
|
1304
|
-
const runtimeCompressionContext = current.runtimeCompressionContext ?? base.runtimeCompressionContext;
|
|
1305
|
-
if (runtimeCompressionContext) {
|
|
1306
|
-
begin.runtimeCompressionContext = runtimeCompressionContext;
|
|
1307
|
-
}
|
|
1308
1182
|
const requested = current.requested ?? base.requested;
|
|
1309
1183
|
if (requested) begin.requested = requested;
|
|
1310
1184
|
const feature = current.feature ?? base.feature;
|
|
@@ -1325,8 +1199,6 @@ function resolveBeginRequest(defaults, override) {
|
|
|
1325
1199
|
if (customerUserEmail) begin.customerUserEmail = customerUserEmail;
|
|
1326
1200
|
const stripeCustomerId = current.stripeCustomerId ?? base.stripeCustomerId;
|
|
1327
1201
|
if (stripeCustomerId) begin.stripeCustomerId = stripeCustomerId;
|
|
1328
|
-
const holdUsd = current.holdUsd ?? base.holdUsd;
|
|
1329
|
-
if (typeof holdUsd === "number") begin.holdUsd = holdUsd;
|
|
1330
1202
|
const batch = current.batch ?? base.batch;
|
|
1331
1203
|
if (typeof batch === "boolean") begin.batch = batch;
|
|
1332
1204
|
const pricingMode = current.pricingMode ?? base.pricingMode;
|
|
@@ -1336,16 +1208,25 @@ function resolveBeginRequest(defaults, override) {
|
|
|
1336
1208
|
}
|
|
1337
1209
|
return begin;
|
|
1338
1210
|
}
|
|
1339
|
-
function
|
|
1211
|
+
function responsesBeginRequest(begin, params) {
|
|
1212
|
+
if (!responsesRequestUsesWebSearch(params)) return begin;
|
|
1340
1213
|
return {
|
|
1341
1214
|
...begin,
|
|
1342
|
-
|
|
1343
|
-
...begin.
|
|
1344
|
-
|
|
1345
|
-
model
|
|
1215
|
+
requested: {
|
|
1216
|
+
...begin.requested ?? {},
|
|
1217
|
+
search: true
|
|
1346
1218
|
}
|
|
1347
1219
|
};
|
|
1348
1220
|
}
|
|
1221
|
+
function responsesRequestUsesWebSearch(params) {
|
|
1222
|
+
if (!params || typeof params !== "object") return false;
|
|
1223
|
+
const tools = params.tools;
|
|
1224
|
+
return Array.isArray(tools) && tools.some((tool) => {
|
|
1225
|
+
if (!tool || typeof tool !== "object") return false;
|
|
1226
|
+
const type = tool.type;
|
|
1227
|
+
return type === "web_search" || type === "web_search_preview";
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1349
1230
|
function transformApiPromise(apiPromise, onResolve, onReject) {
|
|
1350
1231
|
const resolvedPromise = Promise.resolve(apiPromise).then(onResolve, onReject);
|
|
1351
1232
|
if (isObjectRecord(apiPromise)) {
|
|
@@ -1575,6 +1456,11 @@ function inferUsageFromResponse(response, hints, provider = "openai") {
|
|
|
1575
1456
|
return void 0;
|
|
1576
1457
|
}
|
|
1577
1458
|
const cachedInputTokens = candidate.usage.prompt_tokens_details?.cached_tokens ?? candidate.usage.input_tokens_details?.cached_tokens ?? candidate.usage.cached_tokens;
|
|
1459
|
+
const cacheWriteInputTokens = candidate.usage.prompt_tokens_details?.cache_write_tokens ?? candidate.usage.prompt_tokens_details?.cache_creation_tokens ?? candidate.usage.input_tokens_details?.cache_write_tokens ?? candidate.usage.input_tokens_details?.cache_creation_tokens ?? candidate.usage.cache_creation_input_tokens ?? candidate.usage.cache_write_input_tokens ?? candidate.usage.cache_write_tokens;
|
|
1460
|
+
const cacheWrite5mInputTokens = candidate.usage.cache_write_5m_input_tokens ?? candidate.usage.cache_creation?.ephemeral_5m_input_tokens;
|
|
1461
|
+
const cacheWrite1hInputTokens = candidate.usage.cache_write_1h_input_tokens ?? candidate.usage.cache_creation?.ephemeral_1h_input_tokens;
|
|
1462
|
+
const outputSearches = Array.isArray(candidate.output) ? candidate.output.filter((item) => item?.type === "web_search_call").length : 0;
|
|
1463
|
+
const searches = candidate.usage.searches ?? candidate.usage.web_search_queries ?? candidate.usage.server_tool_use?.web_search_requests ?? outputSearches;
|
|
1578
1464
|
const responseEffort = normalizeExecutionReasoningEffort(
|
|
1579
1465
|
candidate.reasoning?.effort
|
|
1580
1466
|
);
|
|
@@ -1584,12 +1470,21 @@ function inferUsageFromResponse(response, hints, provider = "openai") {
|
|
|
1584
1470
|
inputTokens: candidate.usage.prompt_tokens ?? candidate.usage.input_tokens,
|
|
1585
1471
|
responseTokens: candidate.usage.completion_tokens ?? candidate.usage.output_tokens,
|
|
1586
1472
|
cachedInputTokens,
|
|
1473
|
+
cacheWriteInputTokens,
|
|
1474
|
+
cacheWrite5mInputTokens,
|
|
1475
|
+
cacheWrite1hInputTokens,
|
|
1476
|
+
audioInputTokens: candidate.usage.prompt_tokens_details?.audio_tokens ?? candidate.usage.input_tokens_details?.audio_tokens,
|
|
1477
|
+
cachedAudioInputTokens: candidate.usage.prompt_tokens_details?.cached_audio_tokens ?? candidate.usage.input_tokens_details?.cached_audio_tokens ?? candidate.usage.prompt_tokens_details?.cached_tokens_details?.audio_tokens ?? candidate.usage.input_tokens_details?.cached_tokens_details?.audio_tokens,
|
|
1478
|
+
imageInputTokens: candidate.usage.prompt_tokens_details?.image_tokens ?? candidate.usage.input_tokens_details?.image_tokens,
|
|
1479
|
+
imageOutputTokens: candidate.usage.completion_tokens_details?.image_tokens ?? candidate.usage.output_tokens_details?.image_tokens,
|
|
1480
|
+
audioOutputTokens: candidate.usage.completion_tokens_details?.audio_tokens ?? candidate.usage.output_tokens_details?.audio_tokens,
|
|
1587
1481
|
reasoningTokens: candidate.usage.completion_tokens_details?.reasoning_tokens ?? candidate.usage.output_tokens_details?.reasoning_tokens,
|
|
1588
1482
|
...responseEffort ? {
|
|
1589
1483
|
reasoningEffort: responseEffort,
|
|
1590
1484
|
reasoningEffortSource: "provider_response"
|
|
1591
1485
|
} : {},
|
|
1592
|
-
...typeof candidate.reasoning?.type === "string" ? { reasoningMode: candidate.reasoning.type } : typeof candidate.reasoning?.mode === "string" ? { reasoningMode: candidate.reasoning.mode } : {}
|
|
1486
|
+
...typeof candidate.reasoning?.type === "string" ? { reasoningMode: candidate.reasoning.type } : typeof candidate.reasoning?.mode === "string" ? { reasoningMode: candidate.reasoning.mode } : {},
|
|
1487
|
+
...typeof searches === "number" && searches > 0 ? { searches } : {}
|
|
1593
1488
|
};
|
|
1594
1489
|
}
|
|
1595
1490
|
function normalizeExecutionReasoningEffort(value) {
|
|
@@ -1606,29 +1501,64 @@ function openAIRequestExecutionMetadata(params, provider) {
|
|
|
1606
1501
|
const budget = typeof rawBudget === "number" && Number.isInteger(rawBudget) && rawBudget >= 0 ? rawBudget : void 0;
|
|
1607
1502
|
return {
|
|
1608
1503
|
providerUsed: provider,
|
|
1504
|
+
...typeof record.model === "string" ? { modelUsed: record.model } : {},
|
|
1609
1505
|
...effort ? { reasoningEffort: effort, reasoningEffortSource: "provider_request" } : {},
|
|
1610
1506
|
...mode ? { reasoningMode: mode } : {},
|
|
1611
1507
|
...budget !== void 0 ? { reasoningBudgetTokens: budget } : {}
|
|
1612
1508
|
};
|
|
1613
1509
|
}
|
|
1614
|
-
function
|
|
1510
|
+
function tryInferUsageFromStreamChunk(chunk, hints, ctx, provider) {
|
|
1511
|
+
const payload = isObjectRecord(chunk) && isObjectRecord(chunk.response) ? chunk.response : chunk;
|
|
1512
|
+
const inferred = inferUsageFromResponse(payload, hints, provider);
|
|
1513
|
+
if (inferred) {
|
|
1514
|
+
ctx.setUsage(inferred);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
function ensureOpenAIStreamUsage(params) {
|
|
1518
|
+
if (!isObjectRecord(params)) {
|
|
1519
|
+
return params;
|
|
1520
|
+
}
|
|
1521
|
+
const streamOptions = isObjectRecord(params.stream_options) ? params.stream_options : {};
|
|
1522
|
+
return {
|
|
1523
|
+
...params,
|
|
1524
|
+
stream_options: {
|
|
1525
|
+
...streamOptions,
|
|
1526
|
+
include_usage: true
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
function deferUsageFinalization(ctx) {
|
|
1531
|
+
return ctx.deferFinalization?.() ?? (() => Promise.resolve());
|
|
1532
|
+
}
|
|
1533
|
+
function wrapStreamForUsageTap(source, finalize, ctx, onChunk) {
|
|
1615
1534
|
const getIterator = source[Symbol.asyncIterator];
|
|
1616
1535
|
if (typeof getIterator !== "function") {
|
|
1617
1536
|
throw new TypeError("Stream is not async iterable");
|
|
1618
1537
|
}
|
|
1619
1538
|
const iterator = getIterator.call(source);
|
|
1620
1539
|
let completed = false;
|
|
1621
|
-
const invokeFinalize = async () => {
|
|
1540
|
+
const invokeFinalize = async (termination, error) => {
|
|
1622
1541
|
if (completed) return;
|
|
1623
1542
|
completed = true;
|
|
1543
|
+
if (termination === "cancel" || termination === "manual") {
|
|
1544
|
+
ctx.setError({
|
|
1545
|
+
code: "STREAM_ABORTED",
|
|
1546
|
+
message: termination === "cancel" ? "Provider stream consumption was cancelled before completion" : "Provider stream was finalized before completion"
|
|
1547
|
+
});
|
|
1548
|
+
} else if (termination === "error") {
|
|
1549
|
+
ctx.setError({
|
|
1550
|
+
code: "VENDOR_ERROR",
|
|
1551
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1624
1554
|
try {
|
|
1625
|
-
await finalize();
|
|
1626
|
-
} catch (
|
|
1555
|
+
await finalize(termination);
|
|
1556
|
+
} catch (error2) {
|
|
1627
1557
|
ctx.setError({
|
|
1628
1558
|
code: "USAGE_FINALIZE_ERROR",
|
|
1629
|
-
message:
|
|
1559
|
+
message: error2 instanceof Error ? error2.message : String(error2)
|
|
1630
1560
|
});
|
|
1631
|
-
throw
|
|
1561
|
+
throw error2;
|
|
1632
1562
|
}
|
|
1633
1563
|
};
|
|
1634
1564
|
const prototype = Object.getPrototypeOf(source) ?? Object.prototype;
|
|
@@ -1652,12 +1582,15 @@ function wrapStreamForUsageTap(source, finalize, ctx) {
|
|
|
1652
1582
|
value: async (...args) => {
|
|
1653
1583
|
try {
|
|
1654
1584
|
const result = await iterator.next(...args);
|
|
1585
|
+
if (!result.done) {
|
|
1586
|
+
onChunk?.(result.value);
|
|
1587
|
+
}
|
|
1655
1588
|
if (result.done) {
|
|
1656
|
-
await invokeFinalize();
|
|
1589
|
+
await invokeFinalize("complete");
|
|
1657
1590
|
}
|
|
1658
1591
|
return result;
|
|
1659
1592
|
} catch (error) {
|
|
1660
|
-
await invokeFinalize().catch(() => void 0);
|
|
1593
|
+
await invokeFinalize("error", error).catch(() => void 0);
|
|
1661
1594
|
throw error;
|
|
1662
1595
|
}
|
|
1663
1596
|
},
|
|
@@ -1666,39 +1599,49 @@ function wrapStreamForUsageTap(source, finalize, ctx) {
|
|
|
1666
1599
|
});
|
|
1667
1600
|
Object.defineProperty(wrapped, "return", {
|
|
1668
1601
|
value: async (value) => {
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1602
|
+
try {
|
|
1603
|
+
if (typeof iterator.return === "function") {
|
|
1604
|
+
const rawResult = await iterator.return(value);
|
|
1605
|
+
if (!isIteratorResult(rawResult)) {
|
|
1606
|
+
throw new TypeError("Iterator.return() returned an invalid result");
|
|
1607
|
+
}
|
|
1608
|
+
await invokeFinalize("cancel");
|
|
1609
|
+
return rawResult;
|
|
1673
1610
|
}
|
|
1674
|
-
await invokeFinalize();
|
|
1675
|
-
return
|
|
1611
|
+
await invokeFinalize("cancel");
|
|
1612
|
+
return { done: true, value };
|
|
1613
|
+
} catch (error) {
|
|
1614
|
+
await invokeFinalize("error", error).catch(() => void 0);
|
|
1615
|
+
throw error;
|
|
1676
1616
|
}
|
|
1677
|
-
await invokeFinalize();
|
|
1678
|
-
return { done: true, value };
|
|
1679
1617
|
},
|
|
1680
1618
|
configurable: true,
|
|
1681
1619
|
writable: true
|
|
1682
1620
|
});
|
|
1683
1621
|
Object.defineProperty(wrapped, "throw", {
|
|
1684
1622
|
value: async (error) => {
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1623
|
+
try {
|
|
1624
|
+
if (typeof iterator.throw === "function") {
|
|
1625
|
+
const rawResult = await iterator.throw(error);
|
|
1626
|
+
if (!isIteratorResult(rawResult)) {
|
|
1627
|
+
throw new TypeError("Iterator.throw() returned an invalid result");
|
|
1628
|
+
}
|
|
1629
|
+
await invokeFinalize("error", error);
|
|
1630
|
+
return rawResult;
|
|
1689
1631
|
}
|
|
1690
|
-
await invokeFinalize();
|
|
1691
|
-
|
|
1632
|
+
await invokeFinalize("error", error);
|
|
1633
|
+
throw error;
|
|
1634
|
+
} catch (thrownError) {
|
|
1635
|
+
await invokeFinalize("error", thrownError).catch(() => void 0);
|
|
1636
|
+
throw thrownError;
|
|
1692
1637
|
}
|
|
1693
|
-
await invokeFinalize();
|
|
1694
|
-
throw error;
|
|
1695
1638
|
},
|
|
1696
1639
|
configurable: true,
|
|
1697
1640
|
writable: true
|
|
1698
1641
|
});
|
|
1699
1642
|
Object.defineProperty(wrapped, "__usageTapFinalize", {
|
|
1700
1643
|
value: async () => {
|
|
1701
|
-
await invokeFinalize();
|
|
1644
|
+
await invokeFinalize("manual");
|
|
1702
1645
|
},
|
|
1703
1646
|
configurable: true
|
|
1704
1647
|
});
|