promptopskit 0.2.6 → 0.3.1

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.
Files changed (61) hide show
  1. package/README.md +89 -0
  2. package/SKILL.md +49 -0
  3. package/dist/{chunk-PU3UPUND.js → chunk-DDXFDVA6.js} +4 -4
  4. package/dist/{chunk-PU3UPUND.js.map → chunk-DDXFDVA6.js.map} +1 -1
  5. package/dist/chunk-DGFBS7YW.js +101 -0
  6. package/dist/chunk-DGFBS7YW.js.map +1 -0
  7. package/dist/chunk-HWEVRBKZ.js +387 -0
  8. package/dist/chunk-HWEVRBKZ.js.map +1 -0
  9. package/dist/{chunk-5BI5FP5L.js → chunk-LNZS3TIJ.js} +21 -18
  10. package/dist/chunk-LNZS3TIJ.js.map +1 -0
  11. package/dist/{chunk-VYVEVJC3.js → chunk-LRRSI4ON.js} +25 -22
  12. package/dist/chunk-LRRSI4ON.js.map +1 -0
  13. package/dist/chunk-Y2YYEGOY.js +86 -0
  14. package/dist/chunk-Y2YYEGOY.js.map +1 -0
  15. package/dist/cli/index.js +66 -40
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/index.cjs +479 -61
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +8 -4
  20. package/dist/index.d.ts +8 -4
  21. package/dist/index.js +41 -40
  22. package/dist/index.js.map +1 -1
  23. package/dist/providers/anthropic.cjs +64 -19
  24. package/dist/providers/anthropic.cjs.map +1 -1
  25. package/dist/providers/anthropic.d.cts +2 -2
  26. package/dist/providers/anthropic.d.ts +2 -2
  27. package/dist/providers/anthropic.js +2 -2
  28. package/dist/providers/gemini.cjs +60 -15
  29. package/dist/providers/gemini.cjs.map +1 -1
  30. package/dist/providers/gemini.d.cts +2 -2
  31. package/dist/providers/gemini.d.ts +2 -2
  32. package/dist/providers/gemini.js +2 -2
  33. package/dist/providers/openai.cjs +64 -19
  34. package/dist/providers/openai.cjs.map +1 -1
  35. package/dist/providers/openai.d.cts +2 -2
  36. package/dist/providers/openai.d.ts +2 -2
  37. package/dist/providers/openai.js +2 -2
  38. package/dist/providers/openrouter.cjs +66 -21
  39. package/dist/providers/openrouter.cjs.map +1 -1
  40. package/dist/providers/openrouter.d.cts +2 -2
  41. package/dist/providers/openrouter.d.ts +2 -2
  42. package/dist/providers/openrouter.js +3 -3
  43. package/dist/testing.d.cts +1 -1
  44. package/dist/testing.d.ts +1 -1
  45. package/dist/{types-BUzJB5p_.d.cts → types-BsYdPHTU.d.ts} +5 -2
  46. package/dist/{types-DM0-tThJ.d.ts → types-DC-jI6iV.d.cts} +5 -2
  47. package/dist/usagetap/index.cjs +425 -0
  48. package/dist/usagetap/index.cjs.map +1 -0
  49. package/dist/usagetap/index.d.cts +147 -0
  50. package/dist/usagetap/index.d.ts +147 -0
  51. package/dist/usagetap/index.js +31 -0
  52. package/dist/usagetap/index.js.map +1 -0
  53. package/package.json +11 -1
  54. package/dist/chunk-5BI5FP5L.js.map +0 -1
  55. package/dist/chunk-6KGBPHSY.js +0 -56
  56. package/dist/chunk-6KGBPHSY.js.map +0 -1
  57. package/dist/chunk-UYTUGV7Z.js +0 -83
  58. package/dist/chunk-UYTUGV7Z.js.map +0 -1
  59. package/dist/chunk-VYVEVJC3.js.map +0 -1
  60. package/dist/{schema-DJ7C8Q6y.d.cts → schema-Dq0jKest.d.cts} +13 -13
  61. package/dist/{schema-DJ7C8Q6y.d.ts → schema-Dq0jKest.d.ts} +13 -13
package/dist/index.cjs CHANGED
@@ -35,7 +35,15 @@ __export(src_exports, {
35
35
  PromptOpsKit: () => PromptOpsKit,
36
36
  anthropicAdapter: () => anthropicAdapter,
37
37
  applyOverrides: () => applyOverrides,
38
+ applyUsageTapEntitlements: () => applyUsageTapEntitlements,
39
+ beginUsageTapCall: () => beginUsageTapCall,
38
40
  createPromptOpsKit: () => createPromptOpsKit,
41
+ createUsageTapClient: () => createUsageTapClient,
42
+ defaultUsageTapErrorMapper: () => defaultUsageTapErrorMapper,
43
+ endUsageTapCall: () => endUsageTapCall,
44
+ extractAnthropicUsage: () => extractAnthropicUsage,
45
+ extractGeminiUsage: () => extractGeminiUsage,
46
+ extractOpenAIUsage: () => extractOpenAIUsage,
39
47
  extractSections: () => extractSections,
40
48
  extractVariables: () => extractVariables,
41
49
  geminiAdapter: () => geminiAdapter,
@@ -47,8 +55,13 @@ __export(src_exports, {
47
55
  parsePrompt: () => parsePrompt,
48
56
  renderPrompt: () => renderPrompt,
49
57
  resolveIncludes: () => resolveIncludes,
58
+ runAnthropicWithUsageTap: () => runAnthropicWithUsageTap,
59
+ runGeminiWithUsageTap: () => runGeminiWithUsageTap,
60
+ runOpenAIWithUsageTap: () => runOpenAIWithUsageTap,
61
+ runOpenRouterWithUsageTap: () => runOpenRouterWithUsageTap,
50
62
  validateAsset: () => validateAsset,
51
- validateAssetWithIncludes: () => validateAssetWithIncludes
63
+ validateAssetWithIncludes: () => validateAssetWithIncludes,
64
+ withUsageTapCall: () => withUsageTapCall
52
65
  });
53
66
  module.exports = __toCommonJS(src_exports);
54
67
  var import_promises3 = require("fs/promises");
@@ -430,22 +443,36 @@ function renderSections(asset, options = {}) {
430
443
  return result;
431
444
  }
432
445
 
446
+ // src/providers/resolve-asset.ts
447
+ function resolveAssetForProvider(asset, runtime = {}) {
448
+ if (!runtime.environment && !runtime.tier && !runtime.runtime) {
449
+ return asset;
450
+ }
451
+ return applyOverrides(asset, {
452
+ environment: runtime.environment,
453
+ tier: runtime.tier,
454
+ runtime: runtime.runtime
455
+ });
456
+ }
457
+
433
458
  // src/providers/openai.ts
434
459
  var openaiAdapter = {
435
460
  name: "openai",
436
- validate(asset) {
461
+ validate(asset, runtime) {
462
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
437
463
  const errors = [];
438
464
  const warnings = [];
439
- if (!asset.model) {
465
+ if (!resolvedAsset.model) {
440
466
  errors.push("OpenAI adapter requires a model to be specified.");
441
467
  }
442
- if (asset.reasoning?.budget_tokens !== void 0) {
468
+ if (resolvedAsset.reasoning?.budget_tokens !== void 0) {
443
469
  warnings.push("OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.");
444
470
  }
445
471
  return { valid: errors.length === 0, errors, warnings };
446
472
  },
447
473
  render(asset, runtime) {
448
- const sections = renderSections(asset, {
474
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
475
+ const sections = renderSections(resolvedAsset, {
449
476
  variables: runtime.variables,
450
477
  strict: runtime.strict
451
478
  });
@@ -462,26 +489,26 @@ var openaiAdapter = {
462
489
  messages.push({ role: "user", content: sections.prompt_template });
463
490
  }
464
491
  const body = {
465
- model: asset.model,
492
+ model: resolvedAsset.model,
466
493
  messages
467
494
  };
468
- if (asset.sampling?.temperature !== void 0) body.temperature = asset.sampling.temperature;
469
- if (asset.sampling?.top_p !== void 0) body.top_p = asset.sampling.top_p;
470
- if (asset.sampling?.frequency_penalty !== void 0) body.frequency_penalty = asset.sampling.frequency_penalty;
471
- if (asset.sampling?.presence_penalty !== void 0) body.presence_penalty = asset.sampling.presence_penalty;
472
- if (asset.sampling?.stop !== void 0) body.stop = asset.sampling.stop;
473
- if (asset.sampling?.max_output_tokens !== void 0) body.max_tokens = asset.sampling.max_output_tokens;
474
- if (asset.reasoning?.effort) {
475
- body.reasoning_effort = asset.reasoning.effort;
476
- }
477
- if (asset.response?.format === "json") {
495
+ if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
496
+ if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
497
+ if (resolvedAsset.sampling?.frequency_penalty !== void 0) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;
498
+ if (resolvedAsset.sampling?.presence_penalty !== void 0) body.presence_penalty = resolvedAsset.sampling.presence_penalty;
499
+ if (resolvedAsset.sampling?.stop !== void 0) body.stop = resolvedAsset.sampling.stop;
500
+ if (resolvedAsset.sampling?.max_output_tokens !== void 0) body.max_tokens = resolvedAsset.sampling.max_output_tokens;
501
+ if (resolvedAsset.reasoning?.effort) {
502
+ body.reasoning_effort = resolvedAsset.reasoning.effort;
503
+ }
504
+ if (resolvedAsset.response?.format === "json") {
478
505
  body.response_format = { type: "json_object" };
479
506
  }
480
- if (asset.response?.stream !== void 0) {
481
- body.stream = asset.response.stream;
507
+ if (resolvedAsset.response?.stream !== void 0) {
508
+ body.stream = resolvedAsset.response.stream;
482
509
  }
483
- if (asset.tools && asset.tools.length > 0) {
484
- body.tools = asset.tools.map((tool) => {
510
+ if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
511
+ body.tools = resolvedAsset.tools.map((tool) => {
485
512
  if (typeof tool === "string") {
486
513
  const def = runtime.toolRegistry?.[tool];
487
514
  if (def) return def;
@@ -500,7 +527,7 @@ var openaiAdapter = {
500
527
  return {
501
528
  body,
502
529
  provider: "openai",
503
- model: asset.model ?? "unknown"
530
+ model: resolvedAsset.model ?? "unknown"
504
531
  };
505
532
  }
506
533
  };
@@ -508,25 +535,27 @@ var openaiAdapter = {
508
535
  // src/providers/anthropic.ts
509
536
  var anthropicAdapter = {
510
537
  name: "anthropic",
511
- validate(asset) {
538
+ validate(asset, runtime) {
539
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
512
540
  const errors = [];
513
541
  const warnings = [];
514
- if (!asset.model) {
542
+ if (!resolvedAsset.model) {
515
543
  errors.push("Anthropic adapter requires a model to be specified.");
516
544
  }
517
- if (asset.sampling?.frequency_penalty !== void 0) {
545
+ if (resolvedAsset.sampling?.frequency_penalty !== void 0) {
518
546
  warnings.push("Anthropic does not support frequency_penalty. It will be ignored.");
519
547
  }
520
- if (asset.sampling?.presence_penalty !== void 0) {
548
+ if (resolvedAsset.sampling?.presence_penalty !== void 0) {
521
549
  warnings.push("Anthropic does not support presence_penalty. It will be ignored.");
522
550
  }
523
- if (asset.reasoning?.effort !== void 0) {
551
+ if (resolvedAsset.reasoning?.effort !== void 0) {
524
552
  warnings.push("Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.");
525
553
  }
526
554
  return { valid: errors.length === 0, errors, warnings };
527
555
  },
528
556
  render(asset, runtime) {
529
- const sections = renderSections(asset, {
557
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
558
+ const sections = renderSections(resolvedAsset, {
530
559
  variables: runtime.variables,
531
560
  strict: runtime.strict
532
561
  });
@@ -540,31 +569,31 @@ var anthropicAdapter = {
540
569
  messages.push({ role: "user", content: sections.prompt_template });
541
570
  }
542
571
  const body = {
543
- model: asset.model,
572
+ model: resolvedAsset.model,
544
573
  messages
545
574
  };
546
575
  if (sections.system_instructions) {
547
576
  body.system = sections.system_instructions;
548
577
  }
549
- if (asset.sampling?.temperature !== void 0) body.temperature = asset.sampling.temperature;
550
- if (asset.sampling?.top_p !== void 0) body.top_p = asset.sampling.top_p;
551
- if (asset.sampling?.stop !== void 0) body.stop_sequences = asset.sampling.stop;
552
- if (asset.sampling?.max_output_tokens !== void 0) {
553
- body.max_tokens = asset.sampling.max_output_tokens;
578
+ if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
579
+ if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
580
+ if (resolvedAsset.sampling?.stop !== void 0) body.stop_sequences = resolvedAsset.sampling.stop;
581
+ if (resolvedAsset.sampling?.max_output_tokens !== void 0) {
582
+ body.max_tokens = resolvedAsset.sampling.max_output_tokens;
554
583
  } else {
555
584
  body.max_tokens = 4096;
556
585
  }
557
- if (asset.reasoning?.budget_tokens) {
586
+ if (resolvedAsset.reasoning?.budget_tokens) {
558
587
  body.thinking = {
559
588
  type: "enabled",
560
- budget_tokens: asset.reasoning.budget_tokens
589
+ budget_tokens: resolvedAsset.reasoning.budget_tokens
561
590
  };
562
591
  }
563
- if (asset.response?.stream !== void 0) {
564
- body.stream = asset.response.stream;
592
+ if (resolvedAsset.response?.stream !== void 0) {
593
+ body.stream = resolvedAsset.response.stream;
565
594
  }
566
- if (asset.tools && asset.tools.length > 0) {
567
- body.tools = asset.tools.map((tool) => {
595
+ if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
596
+ body.tools = resolvedAsset.tools.map((tool) => {
568
597
  if (typeof tool === "string") {
569
598
  const def = runtime.toolRegistry?.[tool];
570
599
  if (def) return def;
@@ -580,7 +609,7 @@ var anthropicAdapter = {
580
609
  return {
581
610
  body,
582
611
  provider: "anthropic",
583
- model: asset.model ?? "unknown"
612
+ model: resolvedAsset.model ?? "unknown"
584
613
  };
585
614
  }
586
615
  };
@@ -588,22 +617,24 @@ var anthropicAdapter = {
588
617
  // src/providers/gemini.ts
589
618
  var geminiAdapter = {
590
619
  name: "gemini",
591
- validate(asset) {
620
+ validate(asset, runtime) {
621
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
592
622
  const errors = [];
593
623
  const warnings = [];
594
- if (!asset.model) {
624
+ if (!resolvedAsset.model) {
595
625
  errors.push("Gemini adapter requires a model to be specified.");
596
626
  }
597
- if (asset.sampling?.frequency_penalty !== void 0) {
627
+ if (resolvedAsset.sampling?.frequency_penalty !== void 0) {
598
628
  warnings.push("Gemini does not support frequency_penalty. It will be ignored.");
599
629
  }
600
- if (asset.sampling?.presence_penalty !== void 0) {
630
+ if (resolvedAsset.sampling?.presence_penalty !== void 0) {
601
631
  warnings.push("Gemini does not support presence_penalty. It will be ignored.");
602
632
  }
603
633
  return { valid: errors.length === 0, errors, warnings };
604
634
  },
605
635
  render(asset, runtime) {
606
- const sections = renderSections(asset, {
636
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
637
+ const sections = renderSections(resolvedAsset, {
607
638
  variables: runtime.variables,
608
639
  strict: runtime.strict
609
640
  });
@@ -631,23 +662,23 @@ var geminiAdapter = {
631
662
  };
632
663
  }
633
664
  const generationConfig = {};
634
- if (asset.sampling?.temperature !== void 0) generationConfig.temperature = asset.sampling.temperature;
635
- if (asset.sampling?.top_p !== void 0) generationConfig.topP = asset.sampling.top_p;
636
- if (asset.sampling?.max_output_tokens !== void 0) generationConfig.maxOutputTokens = asset.sampling.max_output_tokens;
637
- if (asset.sampling?.stop !== void 0) generationConfig.stopSequences = asset.sampling.stop;
638
- if (asset.response?.format === "json") {
665
+ if (resolvedAsset.sampling?.temperature !== void 0) generationConfig.temperature = resolvedAsset.sampling.temperature;
666
+ if (resolvedAsset.sampling?.top_p !== void 0) generationConfig.topP = resolvedAsset.sampling.top_p;
667
+ if (resolvedAsset.sampling?.max_output_tokens !== void 0) generationConfig.maxOutputTokens = resolvedAsset.sampling.max_output_tokens;
668
+ if (resolvedAsset.sampling?.stop !== void 0) generationConfig.stopSequences = resolvedAsset.sampling.stop;
669
+ if (resolvedAsset.response?.format === "json") {
639
670
  generationConfig.responseMimeType = "application/json";
640
671
  }
641
- if (asset.reasoning?.effort) {
672
+ if (resolvedAsset.reasoning?.effort) {
642
673
  body.thinkingConfig = {
643
- thinkingBudget: asset.reasoning.effort === "high" ? 8192 : asset.reasoning.effort === "medium" ? 4096 : 1024
674
+ thinkingBudget: resolvedAsset.reasoning.effort === "high" ? 8192 : resolvedAsset.reasoning.effort === "medium" ? 4096 : 1024
644
675
  };
645
676
  }
646
677
  if (Object.keys(generationConfig).length > 0) {
647
678
  body.generationConfig = generationConfig;
648
679
  }
649
- if (asset.tools && asset.tools.length > 0) {
650
- const functionDeclarations = asset.tools.map((tool) => {
680
+ if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
681
+ const functionDeclarations = resolvedAsset.tools.map((tool) => {
651
682
  if (typeof tool === "string") {
652
683
  const def = runtime.toolRegistry?.[tool];
653
684
  if (def) return def;
@@ -664,7 +695,7 @@ var geminiAdapter = {
664
695
  return {
665
696
  body,
666
697
  provider: "gemini",
667
- model: asset.model ?? "unknown"
698
+ model: resolvedAsset.model ?? "unknown"
668
699
  };
669
700
  }
670
701
  };
@@ -672,8 +703,8 @@ var geminiAdapter = {
672
703
  // src/providers/openrouter.ts
673
704
  var openrouterAdapter = {
674
705
  name: "openrouter",
675
- validate(asset) {
676
- return openaiAdapter.validate(asset);
706
+ validate(asset, runtime) {
707
+ return openaiAdapter.validate(asset, runtime);
677
708
  },
678
709
  render(asset, runtime) {
679
710
  const result = openaiAdapter.render(asset, runtime);
@@ -934,6 +965,377 @@ var PromptCache = class {
934
965
  }
935
966
  };
936
967
 
968
+ // src/usagetap/client.ts
969
+ var DEFAULT_BASE_URL = "https://api.usagetap.com";
970
+ var ACCEPT_HEADER = "application/vnd.usagetap.v1+json";
971
+ function createUsageTapHttpError(status, body) {
972
+ const error = new Error(`UsageTap request failed with status ${status}`);
973
+ error.statusCode = status;
974
+ error.body = body;
975
+ return error;
976
+ }
977
+ function createUsageTapClient(config) {
978
+ const fetchImpl = config.fetch ?? globalThis.fetch;
979
+ if (!fetchImpl) {
980
+ throw new Error("Fetch API is not available. Provide config.fetch when creating the UsageTap client.");
981
+ }
982
+ const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
983
+ async function request(path, body, init = {}) {
984
+ const response = await fetchImpl(`${baseUrl}${path}`, {
985
+ method: "POST",
986
+ headers: {
987
+ Authorization: `Bearer ${config.apiKey}`,
988
+ Accept: ACCEPT_HEADER,
989
+ "Content-Type": "application/json"
990
+ },
991
+ body: JSON.stringify(body),
992
+ signal: init.signal
993
+ });
994
+ const text = await response.text();
995
+ const parsed = text ? JSON.parse(text) : {};
996
+ if (!response.ok) {
997
+ throw createUsageTapHttpError(response.status, parsed);
998
+ }
999
+ return parsed;
1000
+ }
1001
+ return {
1002
+ request,
1003
+ beginCall(begin, init) {
1004
+ return request("/call_begin", begin, init);
1005
+ },
1006
+ endCall(end, init) {
1007
+ return request("/call_end", end, init);
1008
+ }
1009
+ };
1010
+ }
1011
+
1012
+ // src/usagetap/lifecycle.ts
1013
+ function isObject(value) {
1014
+ return typeof value === "object" && value !== null;
1015
+ }
1016
+ function isInvokeResult(value) {
1017
+ return isObject(value) && "result" in value && "usage" in value;
1018
+ }
1019
+ function getErrorStatusCode(error) {
1020
+ if (!isObject(error)) {
1021
+ return void 0;
1022
+ }
1023
+ if (typeof error.statusCode === "number") {
1024
+ return error.statusCode;
1025
+ }
1026
+ if (typeof error.status === "number") {
1027
+ return error.status;
1028
+ }
1029
+ if (isObject(error.response) && typeof error.response.status === "number") {
1030
+ return error.response.status;
1031
+ }
1032
+ return void 0;
1033
+ }
1034
+ function attachEndErrorCause(thrownError, endError) {
1035
+ if (thrownError instanceof Error) {
1036
+ if (thrownError.cause === void 0) {
1037
+ Object.defineProperty(thrownError, "cause", {
1038
+ value: endError,
1039
+ configurable: true,
1040
+ writable: true
1041
+ });
1042
+ }
1043
+ throw thrownError;
1044
+ }
1045
+ throw new AggregateError([thrownError, endError], "Vendor call failed and UsageTap call_end also failed.");
1046
+ }
1047
+ function defaultUsageTapErrorMapper(error) {
1048
+ return {
1049
+ code: "VENDOR_ERROR",
1050
+ message: String(error)
1051
+ };
1052
+ }
1053
+ function beginUsageTapCall(client, begin, init) {
1054
+ return client.beginCall(begin, init);
1055
+ }
1056
+ function endUsageTapCall(client, end, init) {
1057
+ return client.endCall(end, init);
1058
+ }
1059
+ async function withUsageTapCall(client, options) {
1060
+ const begin = await beginUsageTapCall(client, options.begin, { signal: options.signal });
1061
+ const onError = options.onError ?? defaultUsageTapErrorMapper;
1062
+ let result;
1063
+ let usage;
1064
+ let thrownError;
1065
+ const setUsage = (nextUsage) => {
1066
+ usage = { ...usage, ...nextUsage };
1067
+ };
1068
+ try {
1069
+ const invoked = await options.invoke({
1070
+ begin,
1071
+ setUsage,
1072
+ signal: options.signal
1073
+ });
1074
+ if (isInvokeResult(invoked)) {
1075
+ result = invoked.result;
1076
+ setUsage(invoked.usage);
1077
+ } else {
1078
+ result = invoked;
1079
+ }
1080
+ } catch (error) {
1081
+ thrownError = error;
1082
+ }
1083
+ const effectiveUsage = {
1084
+ ...usage
1085
+ };
1086
+ if (thrownError) {
1087
+ effectiveUsage.error = effectiveUsage.error ?? onError(thrownError);
1088
+ effectiveUsage.responseStatusCode = effectiveUsage.responseStatusCode ?? getErrorStatusCode(thrownError);
1089
+ } else {
1090
+ effectiveUsage.responseStatusCode = effectiveUsage.responseStatusCode ?? 200;
1091
+ }
1092
+ let end;
1093
+ try {
1094
+ end = await endUsageTapCall(client, {
1095
+ callId: begin.data.callId,
1096
+ ...effectiveUsage
1097
+ }, { signal: options.signal });
1098
+ } catch (endError) {
1099
+ if (thrownError) {
1100
+ attachEndErrorCause(thrownError, endError);
1101
+ }
1102
+ throw endError;
1103
+ }
1104
+ if (thrownError) {
1105
+ throw thrownError;
1106
+ }
1107
+ return {
1108
+ result,
1109
+ begin,
1110
+ end,
1111
+ effectiveUsage
1112
+ };
1113
+ }
1114
+
1115
+ // src/usagetap/providers.ts
1116
+ function cloneRequest(request) {
1117
+ return structuredClone(request);
1118
+ }
1119
+ function isObject2(value) {
1120
+ return typeof value === "object" && value !== null;
1121
+ }
1122
+ function isRecordArray(value) {
1123
+ return Array.isArray(value) && value.every((item) => isObject2(item));
1124
+ }
1125
+ function isInvokeResult2(value) {
1126
+ return isObject2(value) && "result" in value && "usage" in value;
1127
+ }
1128
+ function capabilityAllowed(allowed, capability) {
1129
+ return allowed[capability] !== false;
1130
+ }
1131
+ function reasoningLevelOrder(level) {
1132
+ switch (level) {
1133
+ case "HIGH":
1134
+ return 3;
1135
+ case "MEDIUM":
1136
+ return 2;
1137
+ case "LOW":
1138
+ return 1;
1139
+ default:
1140
+ return 0;
1141
+ }
1142
+ }
1143
+ function capOpenAIReasoning(body, allowed) {
1144
+ if (typeof body.reasoning_effort !== "string") {
1145
+ return;
1146
+ }
1147
+ const current = String(body.reasoning_effort).toUpperCase();
1148
+ const allowedLevel = allowed.reasoningLevel ?? "HIGH";
1149
+ if (allowedLevel === "NONE") {
1150
+ delete body.reasoning_effort;
1151
+ return;
1152
+ }
1153
+ if (reasoningLevelOrder(current) > reasoningLevelOrder(allowedLevel)) {
1154
+ body.reasoning_effort = allowedLevel.toLowerCase();
1155
+ }
1156
+ }
1157
+ function capGeminiReasoning(body, allowed) {
1158
+ if (allowed.reasoningLevel === "NONE") {
1159
+ delete body.thinkingConfig;
1160
+ return;
1161
+ }
1162
+ const budgets = {
1163
+ LOW: 1024,
1164
+ MEDIUM: 4096,
1165
+ HIGH: 8192
1166
+ };
1167
+ const allowedBudget = allowed.reasoningLevel ? budgets[allowed.reasoningLevel] : void 0;
1168
+ if (allowedBudget === void 0) {
1169
+ return;
1170
+ }
1171
+ if (!isObject2(body.thinkingConfig)) {
1172
+ body.thinkingConfig = { thinkingBudget: allowedBudget };
1173
+ return;
1174
+ }
1175
+ const thinkingConfig = body.thinkingConfig;
1176
+ if (typeof thinkingConfig.thinkingBudget === "number") {
1177
+ thinkingConfig.thinkingBudget = Math.min(thinkingConfig.thinkingBudget, allowedBudget);
1178
+ return;
1179
+ }
1180
+ thinkingConfig.thinkingBudget = allowedBudget;
1181
+ }
1182
+ function applyModelTier(request, allowed, options) {
1183
+ const nextModel = allowed.premium && options.modelTiers?.premium ? options.modelTiers.premium : allowed.standard && options.modelTiers?.standard ? options.modelTiers.standard : void 0;
1184
+ if (!nextModel) {
1185
+ return;
1186
+ }
1187
+ request.model = nextModel;
1188
+ if (isObject2(request.body) && "model" in request.body) {
1189
+ request.body.model = nextModel;
1190
+ }
1191
+ }
1192
+ function filterOpenAITools(tools, allowed, options) {
1193
+ return tools.filter((tool) => {
1194
+ if (tool.type === "web_search" && allowed.search === false) {
1195
+ return false;
1196
+ }
1197
+ const functionDef = isObject2(tool.function) ? tool.function : void 0;
1198
+ const name = typeof functionDef?.name === "string" ? functionDef.name : typeof tool.name === "string" ? tool.name : typeof tool.type === "string" ? tool.type : void 0;
1199
+ if (!name) {
1200
+ return true;
1201
+ }
1202
+ const capability = options.toolEntitlements?.[name];
1203
+ return capability ? capabilityAllowed(allowed, capability) : true;
1204
+ });
1205
+ }
1206
+ function filterAnthropicTools(tools, allowed, options) {
1207
+ return tools.filter((tool) => {
1208
+ const name = typeof tool.name === "string" ? tool.name : void 0;
1209
+ if (!name) {
1210
+ return true;
1211
+ }
1212
+ const capability = options.toolEntitlements?.[name];
1213
+ return capability ? capabilityAllowed(allowed, capability) : true;
1214
+ });
1215
+ }
1216
+ function filterGeminiTools(tools, allowed, options) {
1217
+ return tools.map((tool) => {
1218
+ const declarations = Array.isArray(tool.functionDeclarations) ? tool.functionDeclarations.filter((declaration) => {
1219
+ if (!isObject2(declaration) || typeof declaration.name !== "string") {
1220
+ return true;
1221
+ }
1222
+ const capability = options.toolEntitlements?.[declaration.name];
1223
+ return capability ? capabilityAllowed(allowed, capability) : true;
1224
+ }) : tool.functionDeclarations;
1225
+ return {
1226
+ ...tool,
1227
+ functionDeclarations: declarations
1228
+ };
1229
+ }).filter((tool) => {
1230
+ if (!Array.isArray(tool.functionDeclarations)) {
1231
+ return true;
1232
+ }
1233
+ return tool.functionDeclarations.length > 0;
1234
+ });
1235
+ }
1236
+ function applyUsageTapEntitlements(request, begin, options = {}) {
1237
+ const nextRequest = cloneRequest(request);
1238
+ const allowed = begin.data.allowed ?? {};
1239
+ applyModelTier(nextRequest, allowed, options);
1240
+ if (!isObject2(nextRequest.body)) {
1241
+ return nextRequest;
1242
+ }
1243
+ if (nextRequest.provider === "openai" || nextRequest.provider === "openrouter") {
1244
+ capOpenAIReasoning(nextRequest.body, allowed);
1245
+ if (isRecordArray(nextRequest.body.tools)) {
1246
+ nextRequest.body.tools = filterOpenAITools(nextRequest.body.tools, allowed, options);
1247
+ }
1248
+ return nextRequest;
1249
+ }
1250
+ if (nextRequest.provider === "gemini") {
1251
+ capGeminiReasoning(nextRequest.body, allowed);
1252
+ if (isRecordArray(nextRequest.body.tools)) {
1253
+ nextRequest.body.tools = filterGeminiTools(nextRequest.body.tools, allowed, options);
1254
+ }
1255
+ return nextRequest;
1256
+ }
1257
+ if (nextRequest.provider === "anthropic" && isRecordArray(nextRequest.body.tools)) {
1258
+ nextRequest.body.tools = filterAnthropicTools(nextRequest.body.tools, allowed, options);
1259
+ }
1260
+ return nextRequest;
1261
+ }
1262
+ function extractOpenAIUsage(response, meta = {}) {
1263
+ const usage = isObject2(response) && isObject2(response.usage) ? response.usage : {};
1264
+ const promptDetails = isObject2(usage.prompt_tokens_details) ? usage.prompt_tokens_details : {};
1265
+ const completionDetails = isObject2(usage.completion_tokens_details) ? usage.completion_tokens_details : {};
1266
+ return {
1267
+ modelUsed: meta.modelUsed,
1268
+ inputTokens: typeof usage.prompt_tokens === "number" ? usage.prompt_tokens : 0,
1269
+ responseTokens: typeof usage.completion_tokens === "number" ? usage.completion_tokens : 0,
1270
+ cachedInputTokens: typeof promptDetails.cached_tokens === "number" ? promptDetails.cached_tokens : void 0,
1271
+ reasoningTokens: typeof completionDetails.reasoning_tokens === "number" ? completionDetails.reasoning_tokens : void 0,
1272
+ responseStatusCode: meta.responseStatusCode ?? 200
1273
+ };
1274
+ }
1275
+ function extractAnthropicUsage(response, meta = {}) {
1276
+ const usage = isObject2(response) && isObject2(response.usage) ? response.usage : {};
1277
+ return {
1278
+ modelUsed: meta.modelUsed,
1279
+ inputTokens: typeof usage.input_tokens === "number" ? usage.input_tokens : 0,
1280
+ responseTokens: typeof usage.output_tokens === "number" ? usage.output_tokens : 0,
1281
+ cachedInputTokens: typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : void 0,
1282
+ responseStatusCode: meta.responseStatusCode ?? 200
1283
+ };
1284
+ }
1285
+ function extractGeminiUsage(response, meta = {}) {
1286
+ const usage = isObject2(response) && isObject2(response.usageMetadata) ? response.usageMetadata : {};
1287
+ return {
1288
+ modelUsed: meta.modelUsed,
1289
+ inputTokens: typeof usage.promptTokenCount === "number" ? usage.promptTokenCount : 0,
1290
+ responseTokens: typeof usage.candidatesTokenCount === "number" ? usage.candidatesTokenCount : 0,
1291
+ cachedInputTokens: typeof usage.cachedContentTokenCount === "number" ? usage.cachedContentTokenCount : void 0,
1292
+ reasoningTokens: typeof usage.thoughtsTokenCount === "number" ? usage.thoughtsTokenCount : void 0,
1293
+ responseStatusCode: meta.responseStatusCode ?? 200
1294
+ };
1295
+ }
1296
+ async function runProviderWithUsageTap(client, options, defaultExtractor) {
1297
+ let requestUsed = cloneRequest(options.request);
1298
+ const lifecycle = await withUsageTapCall(client, {
1299
+ begin: options.begin,
1300
+ signal: options.signal,
1301
+ onError: options.onError ?? defaultUsageTapErrorMapper,
1302
+ invoke: async ({ begin, setUsage }) => {
1303
+ requestUsed = options.entitlementMode === "apply" ? applyUsageTapEntitlements(options.request, begin, options) : cloneRequest(options.request);
1304
+ const invoked = await options.invoke(requestUsed);
1305
+ if (isInvokeResult2(invoked)) {
1306
+ return invoked;
1307
+ }
1308
+ const response = invoked;
1309
+ const usage = (options.extractUsage ?? defaultExtractor)(response, {
1310
+ modelUsed: requestUsed.model,
1311
+ responseStatusCode: 200
1312
+ });
1313
+ setUsage(usage);
1314
+ return response;
1315
+ }
1316
+ });
1317
+ return {
1318
+ response: lifecycle.result,
1319
+ begin: lifecycle.begin,
1320
+ end: lifecycle.end,
1321
+ requestUsed,
1322
+ effectiveUsage: lifecycle.effectiveUsage,
1323
+ allowed: lifecycle.begin.data.allowed ?? {}
1324
+ };
1325
+ }
1326
+ function runOpenAIWithUsageTap(client, options) {
1327
+ return runProviderWithUsageTap(client, options, extractOpenAIUsage);
1328
+ }
1329
+ function runOpenRouterWithUsageTap(client, options) {
1330
+ return runProviderWithUsageTap(client, options, extractOpenAIUsage);
1331
+ }
1332
+ function runAnthropicWithUsageTap(client, options) {
1333
+ return runProviderWithUsageTap(client, options, extractAnthropicUsage);
1334
+ }
1335
+ function runGeminiWithUsageTap(client, options) {
1336
+ return runProviderWithUsageTap(client, options, extractGeminiUsage);
1337
+ }
1338
+
937
1339
  // src/index.ts
938
1340
  function shouldIncludeContextWarningsInResult(policy) {
939
1341
  return policy === void 0 || policy === "auto" || policy === "result-only" || policy === "console-and-result";
@@ -1033,7 +1435,8 @@ ${paths.map((p) => ` - ${p}`).join("\n")}`
1033
1435
  }
1034
1436
  asset = applyOverrides(asset, {
1035
1437
  environment: options.environment,
1036
- tier: options.tier
1438
+ tier: options.tier,
1439
+ runtime: options.runtime
1037
1440
  });
1038
1441
  return asset;
1039
1442
  }
@@ -1046,13 +1449,15 @@ ${paths.map((p) => ` - ${p}`).join("\n")}`
1046
1449
  const { asset } = parsePrompt(options.source);
1047
1450
  const overridden = applyOverrides(asset, {
1048
1451
  environment: options.environment,
1049
- tier: options.tier
1452
+ tier: options.tier,
1453
+ runtime: options.runtime
1050
1454
  });
1051
1455
  resolved = overridden;
1052
1456
  } else if (options.path) {
1053
1457
  resolved = await this.resolvePrompt(options.path, {
1054
1458
  environment: options.environment,
1055
- tier: options.tier
1459
+ tier: options.tier,
1460
+ runtime: options.runtime
1056
1461
  });
1057
1462
  } else {
1058
1463
  throw new Error('Either "path" or "source" must be provided to renderPrompt()');
@@ -1118,7 +1523,15 @@ async function renderPrompt(options) {
1118
1523
  PromptOpsKit,
1119
1524
  anthropicAdapter,
1120
1525
  applyOverrides,
1526
+ applyUsageTapEntitlements,
1527
+ beginUsageTapCall,
1121
1528
  createPromptOpsKit,
1529
+ createUsageTapClient,
1530
+ defaultUsageTapErrorMapper,
1531
+ endUsageTapCall,
1532
+ extractAnthropicUsage,
1533
+ extractGeminiUsage,
1534
+ extractOpenAIUsage,
1122
1535
  extractSections,
1123
1536
  extractVariables,
1124
1537
  geminiAdapter,
@@ -1130,7 +1543,12 @@ async function renderPrompt(options) {
1130
1543
  parsePrompt,
1131
1544
  renderPrompt,
1132
1545
  resolveIncludes,
1546
+ runAnthropicWithUsageTap,
1547
+ runGeminiWithUsageTap,
1548
+ runOpenAIWithUsageTap,
1549
+ runOpenRouterWithUsageTap,
1133
1550
  validateAsset,
1134
- validateAssetWithIncludes
1551
+ validateAssetWithIncludes,
1552
+ withUsageTapCall
1135
1553
  });
1136
1554
  //# sourceMappingURL=index.cjs.map