@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.
package/dist/index.mjs CHANGED
@@ -1148,6 +1148,8 @@ function isOpenRouterModel(model) {
1148
1148
  'openai/gpt-5-mini',
1149
1149
  'openai/gpt-5-nano',
1150
1150
  'openai/gpt-5.1',
1151
+ 'openai/gpt-5.4',
1152
+ 'openai/gpt-5.4-pro',
1151
1153
  'openai/gpt-5.2',
1152
1154
  'openai/gpt-5.2-pro',
1153
1155
  'openai/gpt-5.1-codex',
@@ -8824,78 +8826,107 @@ OpenAI.Videos = Videos;
8824
8826
 
8825
8827
  // llm-openai-config.ts
8826
8828
  const DEFAULT_MODEL = 'gpt-4.1-mini';
8827
- /** Token costs in USD per 1M tokens. Last updated Feb 2025. */
8829
+ const GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS = 272_000;
8830
+ const GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER = 2;
8831
+ const GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER = 1.5;
8832
+ /** Token costs in USD per 1M tokens. Last updated Mar 2026. */
8828
8833
  const openAiModelCosts = {
8829
8834
  'gpt-4o': {
8830
8835
  inputCost: 2.5 / 1_000_000,
8836
+ cacheHitCost: 1.25 / 1_000_000,
8831
8837
  outputCost: 10 / 1_000_000,
8832
8838
  },
8833
8839
  'gpt-4o-mini': {
8834
8840
  inputCost: 0.15 / 1_000_000,
8841
+ cacheHitCost: 0.075 / 1_000_000,
8835
8842
  outputCost: 0.6 / 1_000_000,
8836
8843
  },
8837
8844
  'o1-mini': {
8838
8845
  inputCost: 1.1 / 1_000_000,
8846
+ cacheHitCost: 0.55 / 1_000_000,
8839
8847
  outputCost: 4.4 / 1_000_000,
8840
8848
  },
8841
8849
  'o1': {
8842
8850
  inputCost: 15 / 1_000_000,
8851
+ cacheHitCost: 7.5 / 1_000_000,
8843
8852
  outputCost: 60 / 1_000_000,
8844
8853
  },
8845
8854
  'o3-mini': {
8846
8855
  inputCost: 1.1 / 1_000_000,
8856
+ cacheHitCost: 0.55 / 1_000_000,
8847
8857
  outputCost: 4.4 / 1_000_000,
8848
8858
  },
8849
8859
  'o3': {
8850
8860
  inputCost: 2 / 1_000_000,
8861
+ cacheHitCost: 0.5 / 1_000_000,
8851
8862
  outputCost: 8 / 1_000_000,
8852
8863
  },
8853
8864
  'gpt-4.1': {
8854
8865
  inputCost: 2 / 1_000_000,
8866
+ cacheHitCost: 0.5 / 1_000_000,
8855
8867
  outputCost: 8 / 1_000_000,
8856
8868
  },
8857
8869
  'gpt-4.1-mini': {
8858
8870
  inputCost: 0.4 / 1_000_000,
8871
+ cacheHitCost: 0.1 / 1_000_000,
8859
8872
  outputCost: 1.6 / 1_000_000,
8860
8873
  },
8861
8874
  'gpt-4.1-nano': {
8862
8875
  inputCost: 0.1 / 1_000_000,
8876
+ cacheHitCost: 0.025 / 1_000_000,
8863
8877
  outputCost: 0.4 / 1_000_000,
8864
8878
  },
8865
8879
  'gpt-5': {
8866
8880
  inputCost: 1.25 / 1_000_000,
8881
+ cacheHitCost: 0.125 / 1_000_000,
8867
8882
  outputCost: 10 / 1_000_000,
8868
8883
  },
8869
8884
  'gpt-5-mini': {
8870
8885
  inputCost: 0.25 / 1_000_000,
8886
+ cacheHitCost: 0.025 / 1_000_000,
8871
8887
  outputCost: 2 / 1_000_000,
8872
8888
  },
8873
8889
  'gpt-5-nano': {
8874
8890
  inputCost: 0.05 / 1_000_000,
8891
+ cacheHitCost: 0.005 / 1_000_000,
8875
8892
  outputCost: 0.4 / 1_000_000,
8876
8893
  },
8877
8894
  'gpt-5.1': {
8878
8895
  inputCost: 1.25 / 1_000_000,
8896
+ cacheHitCost: 0.125 / 1_000_000,
8879
8897
  outputCost: 10 / 1_000_000,
8880
8898
  },
8899
+ 'gpt-5.4': {
8900
+ inputCost: 2.5 / 1_000_000,
8901
+ cacheHitCost: 0.25 / 1_000_000,
8902
+ outputCost: 15 / 1_000_000,
8903
+ },
8904
+ 'gpt-5.4-pro': {
8905
+ inputCost: 30 / 1_000_000,
8906
+ outputCost: 180 / 1_000_000,
8907
+ },
8881
8908
  'gpt-5.2': {
8882
- inputCost: 1.5 / 1_000_000,
8883
- outputCost: 12 / 1_000_000,
8909
+ inputCost: 1.75 / 1_000_000,
8910
+ cacheHitCost: 0.175 / 1_000_000,
8911
+ outputCost: 14 / 1_000_000,
8884
8912
  },
8885
8913
  'gpt-5.2-pro': {
8886
- inputCost: 3 / 1_000_000,
8887
- outputCost: 24 / 1_000_000,
8914
+ inputCost: 21 / 1_000_000,
8915
+ outputCost: 168 / 1_000_000,
8888
8916
  },
8889
8917
  'gpt-5.1-codex': {
8890
- inputCost: 1.1 / 1_000_000,
8891
- outputCost: 8.8 / 1_000_000,
8918
+ inputCost: 1.25 / 1_000_000,
8919
+ cacheHitCost: 0.125 / 1_000_000,
8920
+ outputCost: 10 / 1_000_000,
8892
8921
  },
8893
8922
  'gpt-5.1-codex-max': {
8894
- inputCost: 1.8 / 1_000_000,
8895
- outputCost: 14.4 / 1_000_000,
8923
+ inputCost: 1.25 / 1_000_000,
8924
+ cacheHitCost: 0.125 / 1_000_000,
8925
+ outputCost: 10 / 1_000_000,
8896
8926
  },
8897
8927
  'o4-mini': {
8898
8928
  inputCost: 1.1 / 1_000_000,
8929
+ cacheHitCost: 0.275 / 1_000_000,
8899
8930
  outputCost: 4.4 / 1_000_000,
8900
8931
  },
8901
8932
  };
@@ -8911,6 +8942,9 @@ const deepseekModelCosts = {
8911
8942
  outputCost: 2.19 / 1_000_000, // $2.19 per 1M tokens
8912
8943
  },
8913
8944
  };
8945
+ function shouldUseGPT54HighContextPricing(model, inputTokens) {
8946
+ return (model === 'gpt-5.4' || model === 'gpt-5.4-pro') && inputTokens > GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS;
8947
+ }
8914
8948
  /** Image generation costs in USD per image. Based on OpenAI pricing as of Feb 2025. */
8915
8949
  const openAiImageCosts = {
8916
8950
  'gpt-image-1': 0.0075, // $0.0075 per image for gpt-image-1
@@ -8939,8 +8973,8 @@ function calculateImageCost(model, imageCount) {
8939
8973
  * @param model The name of the language model. Supported models are listed in the `openAiModelCosts` and `deepseekModelCosts` objects.
8940
8974
  * @param inputTokens The number of input tokens passed to the language model.
8941
8975
  * @param outputTokens The number of output tokens generated by the language model.
8942
- * @param reasoningTokens The number of output tokens generated by the language model for reasoning. This is only used for Deepseek models.
8943
- * @param cacheHitTokens The number of input tokens that were cache hits for Deepseek models.
8976
+ * @param reasoningTokens The number of output tokens generated by the language model for reasoning.
8977
+ * @param cacheHitTokens The number of input tokens billed at cached-input rates.
8944
8978
  * @returns The cost of calling the language model in USD.
8945
8979
  */
8946
8980
  function calculateCost(provider, model, inputTokens, outputTokens, reasoningTokens, cacheHitTokens) {
@@ -8955,12 +8989,18 @@ function calculateCost(provider, model, inputTokens, outputTokens, reasoningToke
8955
8989
  const modelCosts = provider === 'deepseek' ? deepseekModelCosts[model] : openAiModelCosts[model];
8956
8990
  if (!modelCosts)
8957
8991
  return 0;
8958
- // Calculate input cost based on cache hit/miss for Deepseek
8959
- const inputCost = provider === 'deepseek' && modelCosts.cacheHitCost
8960
- ? (cacheHitTokens || 0) * modelCosts.cacheHitCost + (inputTokens - (cacheHitTokens || 0)) * modelCosts.inputCost
8961
- : inputTokens * modelCosts.inputCost;
8962
- const outputCost = outputTokens * modelCosts.outputCost;
8963
- const reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
8992
+ const boundedCacheHitTokens = Math.min(Math.max(cacheHitTokens || 0, 0), inputTokens);
8993
+ let inputCost = inputTokens * modelCosts.inputCost;
8994
+ if (typeof modelCosts.cacheHitCost === 'number' && boundedCacheHitTokens > 0) {
8995
+ inputCost = boundedCacheHitTokens * modelCosts.cacheHitCost + (inputTokens - boundedCacheHitTokens) * modelCosts.inputCost;
8996
+ }
8997
+ let outputCost = outputTokens * modelCosts.outputCost;
8998
+ let reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
8999
+ if (provider === 'openai' && shouldUseGPT54HighContextPricing(model, inputTokens)) {
9000
+ inputCost *= GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER;
9001
+ outputCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
9002
+ reasoningCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
9003
+ }
8964
9004
  return inputCost + outputCost + reasoningCost;
8965
9005
  }
8966
9006
 
@@ -9358,6 +9398,8 @@ const isSupportedModel = (model) => {
9358
9398
  'gpt-5-mini',
9359
9399
  'gpt-5-nano',
9360
9400
  'gpt-5.1',
9401
+ 'gpt-5.4',
9402
+ 'gpt-5.4-pro',
9361
9403
  'gpt-5.2',
9362
9404
  'gpt-5.2-pro',
9363
9405
  'gpt-5.1-codex',
@@ -9384,6 +9426,8 @@ function supportsTemperature(model) {
9384
9426
  'gpt-5-mini',
9385
9427
  'gpt-5-nano',
9386
9428
  'gpt-5.1',
9429
+ 'gpt-5.4',
9430
+ 'gpt-5.4-pro',
9387
9431
  'gpt-5.2',
9388
9432
  'gpt-5.2-pro',
9389
9433
  'gpt-5.1-codex',
@@ -9411,6 +9455,8 @@ function isGPT5Model(model) {
9411
9455
  'gpt-5-mini',
9412
9456
  'gpt-5-nano',
9413
9457
  'gpt-5.1',
9458
+ 'gpt-5.4',
9459
+ 'gpt-5.4-pro',
9414
9460
  'gpt-5.2',
9415
9461
  'gpt-5.2-pro',
9416
9462
  'gpt-5.1-codex',
@@ -9418,6 +9464,12 @@ function isGPT5Model(model) {
9418
9464
  ];
9419
9465
  return gpt5Models.includes(model);
9420
9466
  }
9467
+ function supportsStructuredOutputs(model) {
9468
+ return normalizeModelName(model) !== 'gpt-5.4-pro';
9469
+ }
9470
+ function supportsDistillation(model) {
9471
+ return normalizeModelName(model) !== 'gpt-5.4-pro';
9472
+ }
9421
9473
  /**
9422
9474
  * Makes a call to OpenAI's Responses API for more advanced use cases with built-in tools.
9423
9475
  *
@@ -9460,8 +9512,15 @@ const makeResponsesAPICall = async (input, options = {}) => {
9460
9512
  input,
9461
9513
  ...cleanOptions,
9462
9514
  };
9515
+ if (requestBody.text?.format?.type === 'json_schema' && !supportsStructuredOutputs(normalizedModel)) {
9516
+ throw new Error(`Model ${normalizedModel} does not support structured outputs`);
9517
+ }
9518
+ if (requestBody.store && !supportsDistillation(normalizedModel)) {
9519
+ throw new Error(`Model ${normalizedModel} does not support distillation`);
9520
+ }
9463
9521
  // Make the API call to the Responses endpoint
9464
9522
  const response = await openai.responses.create(requestBody);
9523
+ const cacheHitTokens = response.usage?.input_tokens_details?.cached_tokens || 0;
9465
9524
  // Extract tool calls from the output
9466
9525
  const toolCalls = response.output
9467
9526
  ?.filter((item) => item.type === 'function_call')
@@ -9501,7 +9560,8 @@ const makeResponsesAPICall = async (input, options = {}) => {
9501
9560
  reasoning_tokens: response.usage?.output_tokens_details?.reasoning_tokens || 0,
9502
9561
  provider: 'openai',
9503
9562
  model: normalizedModel,
9504
- cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0),
9563
+ cache_hit_tokens: cacheHitTokens,
9564
+ cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0, cacheHitTokens),
9505
9565
  },
9506
9566
  tool_calls: toolCalls,
9507
9567
  ...(codeInterpreterOutputs ? { code_interpreter_outputs: codeInterpreterOutputs } : {}),
@@ -9533,7 +9593,8 @@ const makeResponsesAPICall = async (input, options = {}) => {
9533
9593
  reasoning_tokens: response.usage?.output_tokens_details?.reasoning_tokens || 0,
9534
9594
  provider: 'openai',
9535
9595
  model: normalizedModel,
9536
- cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0),
9596
+ cache_hit_tokens: cacheHitTokens,
9597
+ cost: calculateCost('openai', normalizedModel, response.usage?.input_tokens || 0, response.usage?.output_tokens || 0, response.usage?.output_tokens_details?.reasoning_tokens || 0, cacheHitTokens),
9537
9598
  },
9538
9599
  tool_calls: toolCalls,
9539
9600
  ...(codeInterpreterOutputs ? { code_interpreter_outputs: codeInterpreterOutputs } : {}),
@@ -9665,6 +9726,8 @@ const MULTIMODAL_VISION_MODELS = new Set([
9665
9726
  'gpt-5-mini',
9666
9727
  'gpt-5-nano',
9667
9728
  'gpt-5.1',
9729
+ 'gpt-5.4',
9730
+ 'gpt-5.4-pro',
9668
9731
  'gpt-5.2',
9669
9732
  'gpt-5.2-pro',
9670
9733
  'gpt-5.1-codex',