@discomedia/utils 1.0.46 → 1.0.51
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 +10 -1
- package/dist/index-frontend.cjs +151 -11
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +151 -11
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +151 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +151 -11
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +4 -4
- package/dist/test.js +292 -46
- package/dist/test.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/llm-config.d.ts.map +1 -1
- package/dist/types/llm-images.d.ts +6 -3
- package/dist/types/llm-images.d.ts.map +1 -1
- package/dist/types/llm-openai.d.ts.map +1 -1
- package/dist/types/market-time.d.ts +34 -0
- package/dist/types/market-time.d.ts.map +1 -1
- package/dist/types/types/llm-types.d.ts +10 -4
- package/dist/types/types/llm-types.d.ts.map +1 -1
- package/dist/types-frontend/index.d.ts +1 -0
- package/dist/types-frontend/index.d.ts.map +1 -1
- package/dist/types-frontend/llm-config.d.ts.map +1 -1
- package/dist/types-frontend/llm-images.d.ts +6 -3
- package/dist/types-frontend/llm-images.d.ts.map +1 -1
- package/dist/types-frontend/llm-openai.d.ts.map +1 -1
- package/dist/types-frontend/market-time.d.ts +34 -0
- package/dist/types-frontend/market-time.d.ts.map +1 -1
- package/dist/types-frontend/types/llm-types.d.ts +10 -4
- package/dist/types-frontend/types/llm-types.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -17,6 +17,15 @@ npm install @discomedia/utils
|
|
|
17
17
|
> It is included as a dependency because Rollup and TypeScript emit helpers that require `tslib` at build time.
|
|
18
18
|
> Do not remove `tslib` from dependencies, or CI builds will fail.
|
|
19
19
|
|
|
20
|
+
## Updating
|
|
21
|
+
|
|
22
|
+
When updating this repo, it auto-publishes to NPM via a workflow in the [gh_workflows repository](https://github.com/discomedia/gh_workflows).
|
|
23
|
+
|
|
24
|
+
For it to publish, you have to make sure this repo has the NPM_TOKEN environment variable.
|
|
25
|
+
|
|
26
|
+
<img width="1157" height="786" alt="image" src="https://github.com/user-attachments/assets/e6aa7b5a-6584-436c-93ff-e8acafed9697" />
|
|
27
|
+
|
|
28
|
+
|
|
20
29
|
## Usage
|
|
21
30
|
|
|
22
31
|
This package provides two different entry points depending on your environment:
|
|
@@ -119,4 +128,4 @@ Contributions are welcome! Please submit a pull request or open an issue for any
|
|
|
119
128
|
|
|
120
129
|
## Author
|
|
121
130
|
|
|
122
|
-
This project is a product of [Disco Media](https://discomedia.co).
|
|
131
|
+
This project is a product of [Disco Media](https://discomedia.co).
|
package/dist/index-frontend.cjs
CHANGED
|
@@ -9,6 +9,10 @@ function isOpenRouterModel(model) {
|
|
|
9
9
|
'openai/gpt-5-mini',
|
|
10
10
|
'openai/gpt-5-nano',
|
|
11
11
|
'openai/gpt-5.1',
|
|
12
|
+
'openai/gpt-5.2',
|
|
13
|
+
'openai/gpt-5.2-pro',
|
|
14
|
+
'openai/gpt-5.1-codex',
|
|
15
|
+
'openai/gpt-5.1-codex-max',
|
|
12
16
|
'openai/gpt-oss-120b',
|
|
13
17
|
'z.ai/glm-4.5',
|
|
14
18
|
'z.ai/glm-4.5-air',
|
|
@@ -256,7 +260,7 @@ const safeJSON = (text) => {
|
|
|
256
260
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
257
261
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
258
262
|
|
|
259
|
-
const VERSION = '6.
|
|
263
|
+
const VERSION = '6.15.0'; // x-release-please-version
|
|
260
264
|
|
|
261
265
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
262
266
|
const isRunningInBrowser = () => {
|
|
@@ -6097,6 +6101,19 @@ class Responses extends APIResource {
|
|
|
6097
6101
|
cancel(responseID, options) {
|
|
6098
6102
|
return this._client.post(path `/responses/${responseID}/cancel`, options);
|
|
6099
6103
|
}
|
|
6104
|
+
/**
|
|
6105
|
+
* Compact conversation
|
|
6106
|
+
*
|
|
6107
|
+
* @example
|
|
6108
|
+
* ```ts
|
|
6109
|
+
* const compactedResponse = await client.responses.compact({
|
|
6110
|
+
* model: 'gpt-5.2',
|
|
6111
|
+
* });
|
|
6112
|
+
* ```
|
|
6113
|
+
*/
|
|
6114
|
+
compact(body, options) {
|
|
6115
|
+
return this._client.post('/responses/compact', { body, ...options });
|
|
6116
|
+
}
|
|
6100
6117
|
}
|
|
6101
6118
|
Responses.InputItems = InputItems;
|
|
6102
6119
|
Responses.InputTokens = InputTokens;
|
|
@@ -7239,6 +7256,22 @@ const openAiModelCosts = {
|
|
|
7239
7256
|
inputCost: 1.25 / 1_000_000,
|
|
7240
7257
|
outputCost: 10 / 1_000_000,
|
|
7241
7258
|
},
|
|
7259
|
+
'gpt-5.2': {
|
|
7260
|
+
inputCost: 1.5 / 1_000_000,
|
|
7261
|
+
outputCost: 12 / 1_000_000,
|
|
7262
|
+
},
|
|
7263
|
+
'gpt-5.2-pro': {
|
|
7264
|
+
inputCost: 3 / 1_000_000,
|
|
7265
|
+
outputCost: 24 / 1_000_000,
|
|
7266
|
+
},
|
|
7267
|
+
'gpt-5.1-codex': {
|
|
7268
|
+
inputCost: 1.1 / 1_000_000,
|
|
7269
|
+
outputCost: 8.8 / 1_000_000,
|
|
7270
|
+
},
|
|
7271
|
+
'gpt-5.1-codex-max': {
|
|
7272
|
+
inputCost: 1.8 / 1_000_000,
|
|
7273
|
+
outputCost: 14.4 / 1_000_000,
|
|
7274
|
+
},
|
|
7242
7275
|
'o4-mini': {
|
|
7243
7276
|
inputCost: 1.1 / 1_000_000,
|
|
7244
7277
|
outputCost: 4.4 / 1_000_000,
|
|
@@ -7259,6 +7292,7 @@ const deepseekModelCosts = {
|
|
|
7259
7292
|
/** Image generation costs in USD per image. Based on OpenAI pricing as of Feb 2025. */
|
|
7260
7293
|
const openAiImageCosts = {
|
|
7261
7294
|
'gpt-image-1': 0.0075, // $0.0075 per image for gpt-image-1
|
|
7295
|
+
'gpt-image-1.5': 0.0075, // Assumes parity pricing with gpt-image-1 until OpenAI publishes updated rates
|
|
7262
7296
|
};
|
|
7263
7297
|
/**
|
|
7264
7298
|
* Calculates the cost of generating images using OpenAI's Images API.
|
|
@@ -7268,10 +7302,12 @@ const openAiImageCosts = {
|
|
|
7268
7302
|
* @returns The cost of generating the images in USD.
|
|
7269
7303
|
*/
|
|
7270
7304
|
function calculateImageCost(model, imageCount) {
|
|
7271
|
-
if (typeof imageCount !== 'number' || imageCount <= 0) {
|
|
7305
|
+
if (typeof model !== 'string' || typeof imageCount !== 'number' || imageCount <= 0) {
|
|
7272
7306
|
return 0;
|
|
7273
7307
|
}
|
|
7274
7308
|
const costPerImage = openAiImageCosts[model];
|
|
7309
|
+
if (!costPerImage)
|
|
7310
|
+
return 0;
|
|
7275
7311
|
return imageCount * costPerImage;
|
|
7276
7312
|
}
|
|
7277
7313
|
/**
|
|
@@ -7700,6 +7736,10 @@ const isSupportedModel = (model) => {
|
|
|
7700
7736
|
'gpt-5-mini',
|
|
7701
7737
|
'gpt-5-nano',
|
|
7702
7738
|
'gpt-5.1',
|
|
7739
|
+
'gpt-5.2',
|
|
7740
|
+
'gpt-5.2-pro',
|
|
7741
|
+
'gpt-5.1-codex',
|
|
7742
|
+
'gpt-5.1-codex-max',
|
|
7703
7743
|
'o4-mini',
|
|
7704
7744
|
'o3',
|
|
7705
7745
|
].includes(model);
|
|
@@ -7712,7 +7752,21 @@ const isSupportedModel = (model) => {
|
|
|
7712
7752
|
function supportsTemperature(model) {
|
|
7713
7753
|
// Reasoning models don't support temperature
|
|
7714
7754
|
// GPT-5 models also do not support temperature
|
|
7715
|
-
const reasoningAndGPT5Models = [
|
|
7755
|
+
const reasoningAndGPT5Models = [
|
|
7756
|
+
'o1',
|
|
7757
|
+
'o1-mini',
|
|
7758
|
+
'o3-mini',
|
|
7759
|
+
'o4-mini',
|
|
7760
|
+
'o3',
|
|
7761
|
+
'gpt-5',
|
|
7762
|
+
'gpt-5-mini',
|
|
7763
|
+
'gpt-5-nano',
|
|
7764
|
+
'gpt-5.1',
|
|
7765
|
+
'gpt-5.2',
|
|
7766
|
+
'gpt-5.2-pro',
|
|
7767
|
+
'gpt-5.1-codex',
|
|
7768
|
+
'gpt-5.1-codex-max',
|
|
7769
|
+
];
|
|
7716
7770
|
return !reasoningAndGPT5Models.includes(model);
|
|
7717
7771
|
}
|
|
7718
7772
|
/**
|
|
@@ -7730,7 +7784,16 @@ function isReasoningModel(model) {
|
|
|
7730
7784
|
* @returns True if the model is a GPT-5 model, false otherwise.
|
|
7731
7785
|
*/
|
|
7732
7786
|
function isGPT5Model(model) {
|
|
7733
|
-
const gpt5Models = [
|
|
7787
|
+
const gpt5Models = [
|
|
7788
|
+
'gpt-5',
|
|
7789
|
+
'gpt-5-mini',
|
|
7790
|
+
'gpt-5-nano',
|
|
7791
|
+
'gpt-5.1',
|
|
7792
|
+
'gpt-5.2',
|
|
7793
|
+
'gpt-5.2-pro',
|
|
7794
|
+
'gpt-5.1-codex',
|
|
7795
|
+
'gpt-5.1-codex-max',
|
|
7796
|
+
];
|
|
7734
7797
|
return gpt5Models.includes(model);
|
|
7735
7798
|
}
|
|
7736
7799
|
/**
|
|
@@ -7971,6 +8034,20 @@ async function makeLLMCall(input, options = {}) {
|
|
|
7971
8034
|
return await makeResponsesAPICall(processedInput, responsesOptions);
|
|
7972
8035
|
}
|
|
7973
8036
|
|
|
8037
|
+
const DEFAULT_IMAGE_MODEL = 'gpt-image-1.5';
|
|
8038
|
+
const resolveImageModel = (model) => model ?? DEFAULT_IMAGE_MODEL;
|
|
8039
|
+
const MULTIMODAL_VISION_MODELS = new Set([
|
|
8040
|
+
'gpt-4o-mini',
|
|
8041
|
+
'gpt-4o',
|
|
8042
|
+
'gpt-5',
|
|
8043
|
+
'gpt-5-mini',
|
|
8044
|
+
'gpt-5-nano',
|
|
8045
|
+
'gpt-5.1',
|
|
8046
|
+
'gpt-5.2',
|
|
8047
|
+
'gpt-5.2-pro',
|
|
8048
|
+
'gpt-5.1-codex',
|
|
8049
|
+
'gpt-5.1-codex-max',
|
|
8050
|
+
]);
|
|
7974
8051
|
/**
|
|
7975
8052
|
* Makes a call to the OpenAI Images API to generate images based on a text prompt.
|
|
7976
8053
|
*
|
|
@@ -8007,7 +8084,12 @@ async function makeLLMCall(input, options = {}) {
|
|
|
8007
8084
|
* @throws Error if the API call fails or invalid parameters are provided
|
|
8008
8085
|
*/
|
|
8009
8086
|
async function makeImagesCall(prompt, options = {}) {
|
|
8010
|
-
const { size = 'auto', outputFormat = 'webp', compression = 50, quality = 'high', count = 1, background = 'auto', moderation = 'auto', apiKey } = options;
|
|
8087
|
+
const { model, size = 'auto', outputFormat = 'webp', compression = 50, quality = 'high', count = 1, background = 'auto', moderation = 'auto', apiKey, visionModel, } = options;
|
|
8088
|
+
const imageModel = resolveImageModel(model);
|
|
8089
|
+
const supportedVisionModel = visionModel && MULTIMODAL_VISION_MODELS.has(visionModel) ? visionModel : undefined;
|
|
8090
|
+
if (visionModel && !supportedVisionModel) {
|
|
8091
|
+
console.warn(`Vision model ${visionModel} is not recognized as a multimodal OpenAI model. Ignoring for image usage metadata.`);
|
|
8092
|
+
}
|
|
8011
8093
|
// Get API key
|
|
8012
8094
|
const effectiveApiKey = apiKey || process.env.OPENAI_API_KEY;
|
|
8013
8095
|
if (!effectiveApiKey) {
|
|
@@ -8028,7 +8110,7 @@ async function makeImagesCall(prompt, options = {}) {
|
|
|
8028
8110
|
});
|
|
8029
8111
|
// Build the request parameters using OpenAI's type
|
|
8030
8112
|
const requestParams = {
|
|
8031
|
-
model:
|
|
8113
|
+
model: imageModel,
|
|
8032
8114
|
prompt,
|
|
8033
8115
|
n: count || 1,
|
|
8034
8116
|
size: size || 'auto',
|
|
@@ -8052,7 +8134,7 @@ async function makeImagesCall(prompt, options = {}) {
|
|
|
8052
8134
|
throw new Error('No images returned from OpenAI Images API');
|
|
8053
8135
|
}
|
|
8054
8136
|
// Calculate cost
|
|
8055
|
-
const cost = calculateImageCost(
|
|
8137
|
+
const cost = calculateImageCost(imageModel, count || 1);
|
|
8056
8138
|
// Return the response with enhanced usage information
|
|
8057
8139
|
const enhancedResponse = {
|
|
8058
8140
|
...response,
|
|
@@ -8065,8 +8147,9 @@ async function makeImagesCall(prompt, options = {}) {
|
|
|
8065
8147
|
total_tokens: 0,
|
|
8066
8148
|
}),
|
|
8067
8149
|
provider: 'openai',
|
|
8068
|
-
model:
|
|
8150
|
+
model: imageModel,
|
|
8069
8151
|
cost,
|
|
8152
|
+
...(supportedVisionModel ? { visionModel: supportedVisionModel } : {}),
|
|
8070
8153
|
},
|
|
8071
8154
|
};
|
|
8072
8155
|
return enhancedResponse;
|
|
@@ -8767,9 +8850,10 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
|
|
|
8767
8850
|
if (calendar.isEarlyCloseDay(prevMarketDay)) {
|
|
8768
8851
|
prevCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
|
|
8769
8852
|
}
|
|
8770
|
-
const
|
|
8771
|
-
const
|
|
8772
|
-
const
|
|
8853
|
+
const prevNYDate = toNYTime(prevMarketDay);
|
|
8854
|
+
const year = prevNYDate.getUTCFullYear();
|
|
8855
|
+
const month = prevNYDate.getUTCMonth();
|
|
8856
|
+
const day = prevNYDate.getUTCDate();
|
|
8773
8857
|
const closeHour = Math.floor(prevCloseMinutes / 60);
|
|
8774
8858
|
const closeMinute = prevCloseMinutes % 60;
|
|
8775
8859
|
return fromNYTime(new Date(Date.UTC(year, month, day, closeHour, closeMinute, 0, 0)));
|
|
@@ -9298,6 +9382,61 @@ function countTradingDays(startDate, endDate = new Date()) {
|
|
|
9298
9382
|
minutes: Math.round(minutes),
|
|
9299
9383
|
};
|
|
9300
9384
|
}
|
|
9385
|
+
/**
|
|
9386
|
+
* Returns the trading day N days back from a reference date, along with its market open time.
|
|
9387
|
+
* Trading days are counted as full or half trading days (days that end count as 1 full trading day).
|
|
9388
|
+
*
|
|
9389
|
+
* @param options - Object with:
|
|
9390
|
+
* - referenceDate: Date to count back from (default: now)
|
|
9391
|
+
* - days: Number of trading days to go back (must be >= 1)
|
|
9392
|
+
* @returns Object containing:
|
|
9393
|
+
* - date: Trading date in YYYY-MM-DD format
|
|
9394
|
+
* - marketOpenISO: Market open time as ISO string (e.g., "2025-11-15T13:30:00.000Z")
|
|
9395
|
+
* - unixTimestamp: Market open time as Unix timestamp in seconds
|
|
9396
|
+
* @example
|
|
9397
|
+
* ```typescript
|
|
9398
|
+
* // Get the trading day 1 day back (most recent full trading day)
|
|
9399
|
+
* const result = getTradingDaysBack({ days: 1 });
|
|
9400
|
+
* console.log(result.date); // "2025-11-01"
|
|
9401
|
+
* console.log(result.marketOpenISO); // "2025-11-01T13:30:00.000Z"
|
|
9402
|
+
* console.log(result.unixTimestamp); // 1730466600
|
|
9403
|
+
*
|
|
9404
|
+
* // Get the trading day 5 days back from a specific date
|
|
9405
|
+
* const result2 = getTradingDaysBack({
|
|
9406
|
+
* referenceDate: new Date('2025-11-15T12:00:00-05:00'),
|
|
9407
|
+
* days: 5
|
|
9408
|
+
* });
|
|
9409
|
+
* ```
|
|
9410
|
+
*/
|
|
9411
|
+
function getTradingDaysBack(options) {
|
|
9412
|
+
const calendar = new MarketCalendar();
|
|
9413
|
+
const refDate = options.referenceDate || new Date();
|
|
9414
|
+
const daysBack = options.days;
|
|
9415
|
+
if (daysBack < 1) {
|
|
9416
|
+
throw new Error('days must be at least 1');
|
|
9417
|
+
}
|
|
9418
|
+
// Start from the last full trading date relative to reference
|
|
9419
|
+
let targetDate = getLastFullTradingDateImpl(refDate);
|
|
9420
|
+
// Go back the specified number of days (we're already at day 1, so go back days-1 more)
|
|
9421
|
+
for (let i = 1; i < daysBack; i++) {
|
|
9422
|
+
targetDate = calendar.getPreviousMarketDay(targetDate);
|
|
9423
|
+
}
|
|
9424
|
+
// Get market open time for this date
|
|
9425
|
+
const marketTimes = getMarketTimes(targetDate);
|
|
9426
|
+
if (!marketTimes.open) {
|
|
9427
|
+
throw new Error(`No market open time for target date`);
|
|
9428
|
+
}
|
|
9429
|
+
// Format the date string (YYYY-MM-DD) in NY time
|
|
9430
|
+
const nyDate = toNYTime(marketTimes.open);
|
|
9431
|
+
const dateStr = `${nyDate.getUTCFullYear()}-${String(nyDate.getUTCMonth() + 1).padStart(2, '0')}-${String(nyDate.getUTCDate()).padStart(2, '0')}`;
|
|
9432
|
+
const marketOpenISO = marketTimes.open.toISOString();
|
|
9433
|
+
const unixTimestamp = Math.floor(marketTimes.open.getTime() / 1000);
|
|
9434
|
+
return {
|
|
9435
|
+
date: dateStr,
|
|
9436
|
+
marketOpenISO,
|
|
9437
|
+
unixTimestamp,
|
|
9438
|
+
};
|
|
9439
|
+
}
|
|
9301
9440
|
// Export MARKET_TIMES for compatibility
|
|
9302
9441
|
const MARKET_TIMES = {
|
|
9303
9442
|
TIMEZONE: MARKET_CONFIG.TIMEZONE,
|
|
@@ -9344,6 +9483,7 @@ var time = /*#__PURE__*/Object.freeze({
|
|
|
9344
9483
|
getPreviousMarketDay: getPreviousMarketDay,
|
|
9345
9484
|
getStartAndEndDates: getStartAndEndDates,
|
|
9346
9485
|
getTradingDate: getTradingDate,
|
|
9486
|
+
getTradingDaysBack: getTradingDaysBack,
|
|
9347
9487
|
getTradingStartAndEndDates: getTradingStartAndEndDates,
|
|
9348
9488
|
isMarketDay: isMarketDay,
|
|
9349
9489
|
isWithinMarketHours: isWithinMarketHours
|