@ljoukov/llm 7.0.16 → 7.0.18
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 +13 -6
- package/dist/index.cjs +53 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -10
- package/dist/index.d.ts +32 -10
- package/dist/index.js +53 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -209,9 +209,10 @@ console.log(OPENAI_GPT_IMAGE_2_SIZE_CONSTRAINTS);
|
|
|
209
209
|
console.log(images[0]?.mimeType, images[0]?.data.byteLength);
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
-
`generateImages()` is typed as a discriminated union by `model`: `gpt-image-2`
|
|
213
|
-
`imageResolution`, while Gemini image requests use `imageSize`
|
|
214
|
-
`
|
|
212
|
+
`generateImages()` is typed as a discriminated union by `model`: `gpt-image-2` and
|
|
213
|
+
`chatgpt-gpt-image-2` requests use `imageResolution`, while Gemini image requests use `imageSize`
|
|
214
|
+
(`"1K" | "2K" | "4K"`). For GPT Image 2, `OPENAI_GPT_IMAGE_2_RESOLUTIONS` exposes the documented
|
|
215
|
+
popular presets plus
|
|
215
216
|
`"auto"`; custom literal `WIDTHxHEIGHT` resolutions are also accepted when they satisfy
|
|
216
217
|
`OPENAI_GPT_IMAGE_2_SIZE_CONSTRAINTS`: each edge must be at most 3840px, each edge must be a
|
|
217
218
|
multiple of 16px, the long edge must be at most 3:1 relative to the short edge, and total pixels
|
|
@@ -226,14 +227,20 @@ const images = await generateImages({
|
|
|
226
227
|
model: "chatgpt-gpt-image-2",
|
|
227
228
|
stylePrompt: "Warm amber desk light, deep blue night, cinematic laboratory mood.",
|
|
228
229
|
imagePrompts: ["A compact lab bench still life with glassware and an open notebook"],
|
|
230
|
+
imageResolution: "1024x1536",
|
|
231
|
+
imageQuality: "high",
|
|
232
|
+
outputFormat: "jpeg",
|
|
233
|
+
outputCompression: 50,
|
|
234
|
+
action: "generate",
|
|
229
235
|
numImages: 1,
|
|
230
236
|
});
|
|
231
237
|
```
|
|
232
238
|
|
|
233
239
|
That path reuses the same ChatGPT auth setup as other `chatgpt-*` models and sends the request
|
|
234
|
-
through the ChatGPT/Codex Responses `image_generation` built-in tool.
|
|
235
|
-
|
|
236
|
-
`
|
|
240
|
+
through the ChatGPT/Codex Responses `image_generation` built-in tool. `imageResolution`,
|
|
241
|
+
`imageQuality`, `outputFormat`, `outputCompression`, `background`, `moderation`, and `action` are
|
|
242
|
+
passed as tool options. `numImages` is implemented as repeated one-image tool calls because the
|
|
243
|
+
ChatGPT/Codex tool rejects `n` on `tools[0]`.
|
|
237
244
|
|
|
238
245
|
### Streaming (response + thoughts + usage)
|
|
239
246
|
|
package/dist/index.cjs
CHANGED
|
@@ -481,6 +481,7 @@ function resolveChatGptServiceTier(model) {
|
|
|
481
481
|
// src/openai/pricing.ts
|
|
482
482
|
var OPENAI_GPT_55_FAST_MODEL_IDS = ["gpt-5.5-fast", "chatgpt-gpt-5.5-fast"];
|
|
483
483
|
var OPENAI_GPT_55_STANDARD_MODEL_IDS = ["gpt-5.5", "chatgpt-gpt-5.5"];
|
|
484
|
+
var OPENAI_GPT_55_CONCRETE_MODEL_ID_RE = /^(?:chatgpt-)?gpt-5\.5-\d{4}-\d{2}-\d{2}$/u;
|
|
484
485
|
var OPENAI_GPT_54_FAST_MODEL_IDS = ["gpt-5.4-fast", "chatgpt-gpt-5.4-fast"];
|
|
485
486
|
var OPENAI_GPT_54_MINI_MODEL_IDS = ["gpt-5.4-mini", "chatgpt-gpt-5.4-mini"];
|
|
486
487
|
var OPENAI_GPT_54_NANO_MODEL_IDS = ["gpt-5.4-nano"];
|
|
@@ -547,7 +548,7 @@ function getOpenAiPricing(modelId) {
|
|
|
547
548
|
if (OPENAI_GPT_55_FAST_MODEL_IDS.includes(modelId)) {
|
|
548
549
|
return OPENAI_GPT_55_PRIORITY_PRICING;
|
|
549
550
|
}
|
|
550
|
-
if (OPENAI_GPT_55_STANDARD_MODEL_IDS.includes(modelId)) {
|
|
551
|
+
if (OPENAI_GPT_55_STANDARD_MODEL_IDS.includes(modelId) || OPENAI_GPT_55_CONCRETE_MODEL_ID_RE.test(modelId)) {
|
|
551
552
|
return OPENAI_GPT_55_PRICING;
|
|
552
553
|
}
|
|
553
554
|
if (OPENAI_GPT_54_FAST_MODEL_IDS.includes(modelId)) {
|
|
@@ -580,12 +581,14 @@ function resolveUsageNumber(value) {
|
|
|
580
581
|
}
|
|
581
582
|
function estimateCallCostUsd({
|
|
582
583
|
modelId,
|
|
584
|
+
pricingModelId,
|
|
583
585
|
tokens,
|
|
584
586
|
responseImages,
|
|
585
587
|
imageSize,
|
|
586
588
|
imageQuality
|
|
587
589
|
}) {
|
|
588
|
-
const
|
|
590
|
+
const pricingModelIds = resolvePricingModelIds(modelId, pricingModelId);
|
|
591
|
+
const openAiImagePricing = resolvePricing(pricingModelIds, getOpenAiImagePricing);
|
|
589
592
|
if (openAiImagePricing) {
|
|
590
593
|
return estimateOpenAiImageCostUsd({
|
|
591
594
|
pricing: openAiImagePricing,
|
|
@@ -605,7 +608,7 @@ function estimateCallCostUsd({
|
|
|
605
608
|
const toolUsePromptTokens = resolveUsageNumber(tokens.toolUsePromptTokens);
|
|
606
609
|
const promptTokenTotal = promptTokens + toolUsePromptTokens;
|
|
607
610
|
const nonCachedPrompt = Math.max(0, promptTokenTotal - cachedTokens);
|
|
608
|
-
const imagePreviewPricing = getGeminiImagePricing
|
|
611
|
+
const imagePreviewPricing = resolvePricing(pricingModelIds, getGeminiImagePricing);
|
|
609
612
|
if (imagePreviewPricing) {
|
|
610
613
|
const resolvedImageSize = imageSize && imagePreviewPricing.imagePrices[imageSize] ? imageSize : "2K";
|
|
611
614
|
const imageRate = imagePreviewPricing.imagePrices[resolvedImageSize] ?? 0;
|
|
@@ -625,7 +628,7 @@ function estimateCallCostUsd({
|
|
|
625
628
|
const imageOutputCost = imageTokensForPricing * imagePreviewPricing.outputImageRate;
|
|
626
629
|
return inputCost + cachedCost + textOutputCost + imageOutputCost;
|
|
627
630
|
}
|
|
628
|
-
const geminiPricing = getGeminiProPricing
|
|
631
|
+
const geminiPricing = resolvePricing(pricingModelIds, getGeminiProPricing);
|
|
629
632
|
if (geminiPricing) {
|
|
630
633
|
const useHighTier = promptTokenTotal > geminiPricing.threshold;
|
|
631
634
|
const inputRate = useHighTier ? geminiPricing.inputRateHigh : geminiPricing.inputRateLow;
|
|
@@ -637,7 +640,7 @@ function estimateCallCostUsd({
|
|
|
637
640
|
const outputCost = outputTokens * outputRate;
|
|
638
641
|
return inputCost + cachedCost + outputCost;
|
|
639
642
|
}
|
|
640
|
-
const fireworksPricing = getFireworksPricing
|
|
643
|
+
const fireworksPricing = resolvePricing(pricingModelIds, getFireworksPricing);
|
|
641
644
|
if (fireworksPricing) {
|
|
642
645
|
const inputCost = nonCachedPrompt * fireworksPricing.inputRate;
|
|
643
646
|
const cachedCost = cachedTokens * fireworksPricing.cachedRate;
|
|
@@ -645,7 +648,7 @@ function estimateCallCostUsd({
|
|
|
645
648
|
const outputCost = outputTokens * fireworksPricing.outputRate;
|
|
646
649
|
return inputCost + cachedCost + outputCost;
|
|
647
650
|
}
|
|
648
|
-
const openAiPricing = getOpenAiPricing
|
|
651
|
+
const openAiPricing = resolvePricing(pricingModelIds, getOpenAiPricing);
|
|
649
652
|
if (openAiPricing) {
|
|
650
653
|
const inputCost = nonCachedPrompt * openAiPricing.inputRate;
|
|
651
654
|
const cachedCost = cachedTokens * openAiPricing.cachedRate;
|
|
@@ -655,6 +658,21 @@ function estimateCallCostUsd({
|
|
|
655
658
|
}
|
|
656
659
|
return 0;
|
|
657
660
|
}
|
|
661
|
+
function resolvePricingModelIds(modelId, pricingModelId) {
|
|
662
|
+
if (pricingModelId && pricingModelId !== modelId) {
|
|
663
|
+
return [pricingModelId, modelId];
|
|
664
|
+
}
|
|
665
|
+
return [modelId];
|
|
666
|
+
}
|
|
667
|
+
function resolvePricing(modelIds, resolve) {
|
|
668
|
+
for (const modelId of modelIds) {
|
|
669
|
+
const pricing = resolve(modelId);
|
|
670
|
+
if (pricing) {
|
|
671
|
+
return pricing;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return void 0;
|
|
675
|
+
}
|
|
658
676
|
function estimateOpenAiImageCostUsd({
|
|
659
677
|
pricing,
|
|
660
678
|
responseImages,
|
|
@@ -8466,6 +8484,7 @@ async function runTextCall(params) {
|
|
|
8466
8484
|
const outputAttachments = collectLoggedAttachmentsFromLlmParts(mergedParts, "output");
|
|
8467
8485
|
const costUsd = estimateCallCostUsd({
|
|
8468
8486
|
modelId: modelVersion,
|
|
8487
|
+
pricingModelId: request.model,
|
|
8469
8488
|
tokens: latestUsage,
|
|
8470
8489
|
responseImages,
|
|
8471
8490
|
imageSize: request.imageSize
|
|
@@ -9209,6 +9228,7 @@ async function runToolLoop(request) {
|
|
|
9209
9228
|
const modelCompletedAtMs = Date.now();
|
|
9210
9229
|
const stepCostUsd = estimateCallCostUsd({
|
|
9211
9230
|
modelId: modelVersion,
|
|
9231
|
+
pricingModelId: request.model,
|
|
9212
9232
|
tokens: usageTokens,
|
|
9213
9233
|
responseImages: 0
|
|
9214
9234
|
});
|
|
@@ -9540,6 +9560,7 @@ async function runToolLoop(request) {
|
|
|
9540
9560
|
usageTokens = extractChatGptUsageTokens(response.usage);
|
|
9541
9561
|
const stepCostUsd = estimateCallCostUsd({
|
|
9542
9562
|
modelId: modelVersion,
|
|
9563
|
+
pricingModelId: request.model,
|
|
9543
9564
|
tokens: usageTokens,
|
|
9544
9565
|
responseImages: 0
|
|
9545
9566
|
});
|
|
@@ -9868,6 +9889,7 @@ async function runToolLoop(request) {
|
|
|
9868
9889
|
usageTokens = extractFireworksUsageTokens(response.usage);
|
|
9869
9890
|
const stepCostUsd = estimateCallCostUsd({
|
|
9870
9891
|
modelId: modelVersion,
|
|
9892
|
+
pricingModelId: request.model,
|
|
9871
9893
|
tokens: usageTokens,
|
|
9872
9894
|
responseImages: 0
|
|
9873
9895
|
});
|
|
@@ -10230,6 +10252,7 @@ async function runToolLoop(request) {
|
|
|
10230
10252
|
);
|
|
10231
10253
|
const stepCostUsd = estimateCallCostUsd({
|
|
10232
10254
|
modelId: modelVersion,
|
|
10255
|
+
pricingModelId: request.model,
|
|
10233
10256
|
tokens: usageTokens,
|
|
10234
10257
|
responseImages: 0
|
|
10235
10258
|
});
|
|
@@ -10584,7 +10607,7 @@ function buildOpenAiImagePrompt(params) {
|
|
|
10584
10607
|
params.imagePrompt.trim()
|
|
10585
10608
|
].filter((line) => line.length > 0).join("\n");
|
|
10586
10609
|
}
|
|
10587
|
-
function
|
|
10610
|
+
function resolveGptImage2RequestParams(request) {
|
|
10588
10611
|
if (request.partialImages !== void 0) {
|
|
10589
10612
|
throw new Error("partialImages is only supported for streaming image generation.");
|
|
10590
10613
|
}
|
|
@@ -10598,7 +10621,7 @@ function resolveOpenAiImageRequestParams(request) {
|
|
|
10598
10621
|
const sizeValidation = validateOpenAiGptImage2Resolution(size);
|
|
10599
10622
|
if (!sizeValidation.valid) {
|
|
10600
10623
|
throw new Error(
|
|
10601
|
-
`imageResolution ${JSON.stringify(size)} is not supported by
|
|
10624
|
+
`imageResolution ${JSON.stringify(size)} is not supported by ${request.model}: ${sizeValidation.reason}`
|
|
10602
10625
|
);
|
|
10603
10626
|
}
|
|
10604
10627
|
return {
|
|
@@ -10641,7 +10664,7 @@ async function generateImagesWithOpenAiImageApi(request) {
|
|
|
10641
10664
|
model: request.model
|
|
10642
10665
|
});
|
|
10643
10666
|
const startedAtMs = Date.now();
|
|
10644
|
-
const params =
|
|
10667
|
+
const params = resolveGptImage2RequestParams(request);
|
|
10645
10668
|
const styleImages = await createOpenAiStyleImageFiles(request.styleImages);
|
|
10646
10669
|
const hasStyleImages = Boolean(styleImages && styleImages.length > 0);
|
|
10647
10670
|
const outputMimeType = resolveOpenAiImageMimeType(params.outputFormat);
|
|
@@ -10769,7 +10792,8 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10769
10792
|
model: request.model
|
|
10770
10793
|
});
|
|
10771
10794
|
const startedAtMs = Date.now();
|
|
10772
|
-
const
|
|
10795
|
+
const params = resolveGptImage2RequestParams(request);
|
|
10796
|
+
const outputMimeType = resolveOpenAiImageMimeType(params.outputFormat);
|
|
10773
10797
|
let totalUsage;
|
|
10774
10798
|
let costUsd = 0;
|
|
10775
10799
|
let outputImages = 0;
|
|
@@ -10777,7 +10801,7 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10777
10801
|
type: "llm.call.started",
|
|
10778
10802
|
imagePromptCount: promptEntries.length,
|
|
10779
10803
|
styleImageCount: request.styleImages?.length ?? 0,
|
|
10780
|
-
numImagesPerPrompt
|
|
10804
|
+
numImagesPerPrompt: params.n
|
|
10781
10805
|
});
|
|
10782
10806
|
try {
|
|
10783
10807
|
const images = [];
|
|
@@ -10787,7 +10811,7 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10787
10811
|
imagePrompt,
|
|
10788
10812
|
hasStyleImages: Boolean(request.styleImages && request.styleImages.length > 0)
|
|
10789
10813
|
});
|
|
10790
|
-
for (let imageIndex = 0; imageIndex <
|
|
10814
|
+
for (let imageIndex = 0; imageIndex < params.n; imageIndex += 1) {
|
|
10791
10815
|
const chatGptInput = toChatGptInput(
|
|
10792
10816
|
buildChatGptImageInputContent({
|
|
10793
10817
|
prompt,
|
|
@@ -10804,11 +10828,22 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10804
10828
|
model: providerInfo.model,
|
|
10805
10829
|
store: false,
|
|
10806
10830
|
stream: true,
|
|
10807
|
-
instructions: chatGptInput.instructions ?? "Use the image_generation tool to generate exactly one
|
|
10831
|
+
instructions: chatGptInput.instructions ?? "Use the image_generation tool to generate exactly one image. Do not return prose instead of the image.",
|
|
10808
10832
|
input: preparedInput,
|
|
10809
10833
|
tool_choice: "required",
|
|
10810
10834
|
parallel_tool_calls: false,
|
|
10811
|
-
tools: [
|
|
10835
|
+
tools: [
|
|
10836
|
+
{
|
|
10837
|
+
type: "image_generation",
|
|
10838
|
+
size: params.size,
|
|
10839
|
+
quality: params.quality,
|
|
10840
|
+
output_format: params.outputFormat ?? "png",
|
|
10841
|
+
...request.outputCompression !== void 0 ? { output_compression: request.outputCompression } : {},
|
|
10842
|
+
...params.background ? { background: params.background } : {},
|
|
10843
|
+
...params.moderation ? { moderation: params.moderation } : {},
|
|
10844
|
+
...request.action ? { action: request.action } : {}
|
|
10845
|
+
}
|
|
10846
|
+
]
|
|
10812
10847
|
},
|
|
10813
10848
|
signal: request.signal
|
|
10814
10849
|
});
|
|
@@ -10820,7 +10855,7 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10820
10855
|
}
|
|
10821
10856
|
for (const call of result.imageGenerationCalls) {
|
|
10822
10857
|
images.push({
|
|
10823
|
-
mimeType:
|
|
10858
|
+
mimeType: outputMimeType,
|
|
10824
10859
|
data: import_node_buffer4.Buffer.from(call.result, "base64")
|
|
10825
10860
|
});
|
|
10826
10861
|
}
|
|
@@ -10831,8 +10866,8 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10831
10866
|
modelId: request.model,
|
|
10832
10867
|
tokens: usage,
|
|
10833
10868
|
responseImages: result.imageGenerationCalls.length,
|
|
10834
|
-
imageSize:
|
|
10835
|
-
imageQuality:
|
|
10869
|
+
imageSize: params.size,
|
|
10870
|
+
imageQuality: params.quality
|
|
10836
10871
|
});
|
|
10837
10872
|
}
|
|
10838
10873
|
}
|
|
@@ -10844,7 +10879,7 @@ async function generateImagesWithChatGptImageTool(request) {
|
|
|
10844
10879
|
usage: totalUsage,
|
|
10845
10880
|
costUsd,
|
|
10846
10881
|
imageCount: images.length,
|
|
10847
|
-
attempts: promptEntries.length *
|
|
10882
|
+
attempts: promptEntries.length * params.n
|
|
10848
10883
|
});
|
|
10849
10884
|
return images;
|
|
10850
10885
|
} catch (error) {
|