@discomedia/utils 1.0.61 → 1.0.62

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.
@@ -7,6 +7,8 @@ function isOpenRouterModel(model) {
7
7
  'openai/gpt-5-mini',
8
8
  'openai/gpt-5-nano',
9
9
  'openai/gpt-5.1',
10
+ 'openai/gpt-5.4',
11
+ 'openai/gpt-5.4-pro',
10
12
  'openai/gpt-5.2',
11
13
  'openai/gpt-5.2-pro',
12
14
  'openai/gpt-5.1-codex',
@@ -7470,78 +7472,107 @@ OpenAI.Videos = Videos;
7470
7472
 
7471
7473
  // llm-openai-config.ts
7472
7474
  const DEFAULT_MODEL = 'gpt-4.1-mini';
7473
- /** Token costs in USD per 1M tokens. Last updated Feb 2025. */
7475
+ const GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS = 272_000;
7476
+ const GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER = 2;
7477
+ const GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER = 1.5;
7478
+ /** Token costs in USD per 1M tokens. Last updated Mar 2026. */
7474
7479
  const openAiModelCosts = {
7475
7480
  'gpt-4o': {
7476
7481
  inputCost: 2.5 / 1_000_000,
7482
+ cacheHitCost: 1.25 / 1_000_000,
7477
7483
  outputCost: 10 / 1_000_000,
7478
7484
  },
7479
7485
  'gpt-4o-mini': {
7480
7486
  inputCost: 0.15 / 1_000_000,
7487
+ cacheHitCost: 0.075 / 1_000_000,
7481
7488
  outputCost: 0.6 / 1_000_000,
7482
7489
  },
7483
7490
  'o1-mini': {
7484
7491
  inputCost: 1.1 / 1_000_000,
7492
+ cacheHitCost: 0.55 / 1_000_000,
7485
7493
  outputCost: 4.4 / 1_000_000,
7486
7494
  },
7487
7495
  'o1': {
7488
7496
  inputCost: 15 / 1_000_000,
7497
+ cacheHitCost: 7.5 / 1_000_000,
7489
7498
  outputCost: 60 / 1_000_000,
7490
7499
  },
7491
7500
  'o3-mini': {
7492
7501
  inputCost: 1.1 / 1_000_000,
7502
+ cacheHitCost: 0.55 / 1_000_000,
7493
7503
  outputCost: 4.4 / 1_000_000,
7494
7504
  },
7495
7505
  'o3': {
7496
7506
  inputCost: 2 / 1_000_000,
7507
+ cacheHitCost: 0.5 / 1_000_000,
7497
7508
  outputCost: 8 / 1_000_000,
7498
7509
  },
7499
7510
  'gpt-4.1': {
7500
7511
  inputCost: 2 / 1_000_000,
7512
+ cacheHitCost: 0.5 / 1_000_000,
7501
7513
  outputCost: 8 / 1_000_000,
7502
7514
  },
7503
7515
  'gpt-4.1-mini': {
7504
7516
  inputCost: 0.4 / 1_000_000,
7517
+ cacheHitCost: 0.1 / 1_000_000,
7505
7518
  outputCost: 1.6 / 1_000_000,
7506
7519
  },
7507
7520
  'gpt-4.1-nano': {
7508
7521
  inputCost: 0.1 / 1_000_000,
7522
+ cacheHitCost: 0.025 / 1_000_000,
7509
7523
  outputCost: 0.4 / 1_000_000,
7510
7524
  },
7511
7525
  'gpt-5': {
7512
7526
  inputCost: 1.25 / 1_000_000,
7527
+ cacheHitCost: 0.125 / 1_000_000,
7513
7528
  outputCost: 10 / 1_000_000,
7514
7529
  },
7515
7530
  'gpt-5-mini': {
7516
7531
  inputCost: 0.25 / 1_000_000,
7532
+ cacheHitCost: 0.025 / 1_000_000,
7517
7533
  outputCost: 2 / 1_000_000,
7518
7534
  },
7519
7535
  'gpt-5-nano': {
7520
7536
  inputCost: 0.05 / 1_000_000,
7537
+ cacheHitCost: 0.005 / 1_000_000,
7521
7538
  outputCost: 0.4 / 1_000_000,
7522
7539
  },
7523
7540
  'gpt-5.1': {
7524
7541
  inputCost: 1.25 / 1_000_000,
7542
+ cacheHitCost: 0.125 / 1_000_000,
7525
7543
  outputCost: 10 / 1_000_000,
7526
7544
  },
7545
+ 'gpt-5.4': {
7546
+ inputCost: 2.5 / 1_000_000,
7547
+ cacheHitCost: 0.25 / 1_000_000,
7548
+ outputCost: 15 / 1_000_000,
7549
+ },
7550
+ 'gpt-5.4-pro': {
7551
+ inputCost: 30 / 1_000_000,
7552
+ outputCost: 180 / 1_000_000,
7553
+ },
7527
7554
  'gpt-5.2': {
7528
- inputCost: 1.5 / 1_000_000,
7529
- outputCost: 12 / 1_000_000,
7555
+ inputCost: 1.75 / 1_000_000,
7556
+ cacheHitCost: 0.175 / 1_000_000,
7557
+ outputCost: 14 / 1_000_000,
7530
7558
  },
7531
7559
  'gpt-5.2-pro': {
7532
- inputCost: 3 / 1_000_000,
7533
- outputCost: 24 / 1_000_000,
7560
+ inputCost: 21 / 1_000_000,
7561
+ outputCost: 168 / 1_000_000,
7534
7562
  },
7535
7563
  'gpt-5.1-codex': {
7536
- inputCost: 1.1 / 1_000_000,
7537
- outputCost: 8.8 / 1_000_000,
7564
+ inputCost: 1.25 / 1_000_000,
7565
+ cacheHitCost: 0.125 / 1_000_000,
7566
+ outputCost: 10 / 1_000_000,
7538
7567
  },
7539
7568
  'gpt-5.1-codex-max': {
7540
- inputCost: 1.8 / 1_000_000,
7541
- outputCost: 14.4 / 1_000_000,
7569
+ inputCost: 1.25 / 1_000_000,
7570
+ cacheHitCost: 0.125 / 1_000_000,
7571
+ outputCost: 10 / 1_000_000,
7542
7572
  },
7543
7573
  'o4-mini': {
7544
7574
  inputCost: 1.1 / 1_000_000,
7575
+ cacheHitCost: 0.275 / 1_000_000,
7545
7576
  outputCost: 4.4 / 1_000_000,
7546
7577
  },
7547
7578
  };
@@ -7557,6 +7588,9 @@ const deepseekModelCosts = {
7557
7588
  outputCost: 2.19 / 1_000_000, // $2.19 per 1M tokens
7558
7589
  },
7559
7590
  };
7591
+ function shouldUseGPT54HighContextPricing(model, inputTokens) {
7592
+ return (model === 'gpt-5.4' || model === 'gpt-5.4-pro') && inputTokens > GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS;
7593
+ }
7560
7594
  /** Image generation costs in USD per image. Based on OpenAI pricing as of Feb 2025. */
7561
7595
  const openAiImageCosts = {
7562
7596
  'gpt-image-1': 0.0075, // $0.0075 per image for gpt-image-1
@@ -7585,8 +7619,8 @@ function calculateImageCost(model, imageCount) {
7585
7619
  * @param model The name of the language model. Supported models are listed in the `openAiModelCosts` and `deepseekModelCosts` objects.
7586
7620
  * @param inputTokens The number of input tokens passed to the language model.
7587
7621
  * @param outputTokens The number of output tokens generated by the language model.
7588
- * @param reasoningTokens The number of output tokens generated by the language model for reasoning. This is only used for Deepseek models.
7589
- * @param cacheHitTokens The number of input tokens that were cache hits for Deepseek models.
7622
+ * @param reasoningTokens The number of output tokens generated by the language model for reasoning.
7623
+ * @param cacheHitTokens The number of input tokens billed at cached-input rates.
7590
7624
  * @returns The cost of calling the language model in USD.
7591
7625
  */
7592
7626
  function calculateCost(provider, model, inputTokens, outputTokens, reasoningTokens, cacheHitTokens) {
@@ -7601,12 +7635,18 @@ function calculateCost(provider, model, inputTokens, outputTokens, reasoningToke
7601
7635
  const modelCosts = provider === 'deepseek' ? deepseekModelCosts[model] : openAiModelCosts[model];
7602
7636
  if (!modelCosts)
7603
7637
  return 0;
7604
- // Calculate input cost based on cache hit/miss for Deepseek
7605
- const inputCost = provider === 'deepseek' && modelCosts.cacheHitCost
7606
- ? (cacheHitTokens || 0) * modelCosts.cacheHitCost + (inputTokens - (cacheHitTokens || 0)) * modelCosts.inputCost
7607
- : inputTokens * modelCosts.inputCost;
7608
- const outputCost = outputTokens * modelCosts.outputCost;
7609
- const reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
7638
+ const boundedCacheHitTokens = Math.min(Math.max(cacheHitTokens || 0, 0), inputTokens);
7639
+ let inputCost = inputTokens * modelCosts.inputCost;
7640
+ if (typeof modelCosts.cacheHitCost === 'number' && boundedCacheHitTokens > 0) {
7641
+ inputCost = boundedCacheHitTokens * modelCosts.cacheHitCost + (inputTokens - boundedCacheHitTokens) * modelCosts.inputCost;
7642
+ }
7643
+ let outputCost = outputTokens * modelCosts.outputCost;
7644
+ let reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
7645
+ if (provider === 'openai' && shouldUseGPT54HighContextPricing(model, inputTokens)) {
7646
+ inputCost *= GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER;
7647
+ outputCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
7648
+ reasoningCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
7649
+ }
7610
7650
  return inputCost + outputCost + reasoningCost;
7611
7651
  }
7612
7652
 
@@ -8004,6 +8044,8 @@ const isSupportedModel = (model) => {
8004
8044
  'gpt-5-mini',
8005
8045
  'gpt-5-nano',
8006
8046
  'gpt-5.1',
8047
+ 'gpt-5.4',
8048
+ 'gpt-5.4-pro',
8007
8049
  'gpt-5.2',
8008
8050
  'gpt-5.2-pro',
8009
8051
  'gpt-5.1-codex',
@@ -8030,6 +8072,8 @@ function supportsTemperature(model) {
8030
8072
  'gpt-5-mini',
8031
8073
  'gpt-5-nano',
8032
8074
  'gpt-5.1',
8075
+ 'gpt-5.4',
8076
+ 'gpt-5.4-pro',
8033
8077
  'gpt-5.2',
8034
8078
  'gpt-5.2-pro',
8035
8079
  'gpt-5.1-codex',
@@ -8057,6 +8101,8 @@ function isGPT5Model(model) {
8057
8101
  'gpt-5-mini',
8058
8102
  'gpt-5-nano',
8059
8103
  'gpt-5.1',
8104
+ 'gpt-5.4',
8105
+ 'gpt-5.4-pro',
8060
8106
  'gpt-5.2',
8061
8107
  'gpt-5.2-pro',
8062
8108
  'gpt-5.1-codex',
@@ -8064,6 +8110,12 @@ function isGPT5Model(model) {
8064
8110
  ];
8065
8111
  return gpt5Models.includes(model);
8066
8112
  }
8113
+ function supportsStructuredOutputs(model) {
8114
+ return normalizeModelName(model) !== 'gpt-5.4-pro';
8115
+ }
8116
+ function supportsDistillation(model) {
8117
+ return normalizeModelName(model) !== 'gpt-5.4-pro';
8118
+ }
8067
8119
  /**
8068
8120
  * Makes a call to OpenAI's Responses API for more advanced use cases with built-in tools.
8069
8121
  *
@@ -8106,8 +8158,15 @@ const makeResponsesAPICall = async (input, options = {}) => {
8106
8158
  input,
8107
8159
  ...cleanOptions,
8108
8160
  };
8161
+ if (requestBody.text?.format?.type === 'json_schema' && !supportsStructuredOutputs(normalizedModel)) {
8162
+ throw new Error(`Model ${normalizedModel} does not support structured outputs`);
8163
+ }
8164
+ if (requestBody.store && !supportsDistillation(normalizedModel)) {
8165
+ throw new Error(`Model ${normalizedModel} does not support distillation`);
8166
+ }
8109
8167
  // Make the API call to the Responses endpoint
8110
8168
  const response = await openai.responses.create(requestBody);
8169
+ const cacheHitTokens = response.usage?.input_tokens_details?.cached_tokens || 0;
8111
8170
  // Extract tool calls from the output
8112
8171
  const toolCalls = response.output
8113
8172
  ?.filter((item) => item.type === 'function_call')
@@ -8147,7 +8206,8 @@ const makeResponsesAPICall = async (input, options = {}) => {
8147
8206
  reasoning_tokens: response.usage?.output_tokens_details?.reasoning_tokens || 0,
8148
8207
  provider: 'openai',
8149
8208
  model: normalizedModel,
8150
- cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0),
8209
+ cache_hit_tokens: cacheHitTokens,
8210
+ cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0, cacheHitTokens),
8151
8211
  },
8152
8212
  tool_calls: toolCalls,
8153
8213
  ...(codeInterpreterOutputs ? { code_interpreter_outputs: codeInterpreterOutputs } : {}),
@@ -8179,7 +8239,8 @@ const makeResponsesAPICall = async (input, options = {}) => {
8179
8239
  reasoning_tokens: response.usage?.output_tokens_details?.reasoning_tokens || 0,
8180
8240
  provider: 'openai',
8181
8241
  model: normalizedModel,
8182
- cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0),
8242
+ cache_hit_tokens: cacheHitTokens,
8243
+ cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0, cacheHitTokens),
8183
8244
  },
8184
8245
  tool_calls: toolCalls,
8185
8246
  ...(codeInterpreterOutputs ? { code_interpreter_outputs: codeInterpreterOutputs } : {}),
@@ -8311,6 +8372,8 @@ const MULTIMODAL_VISION_MODELS = new Set([
8311
8372
  'gpt-5-mini',
8312
8373
  'gpt-5-nano',
8313
8374
  'gpt-5.1',
8375
+ 'gpt-5.4',
8376
+ 'gpt-5.4-pro',
8314
8377
  'gpt-5.2',
8315
8378
  'gpt-5.2-pro',
8316
8379
  'gpt-5.1-codex',