@ljoukov/llm 7.0.13 → 7.0.15
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 +73 -3
- package/dist/index.cjs +346 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -4
- package/dist/index.d.ts +76 -4
- package/dist/index.js +339 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -218,6 +218,23 @@ multiple of 16px, the long edge must be at most 3:1 relative to the short edge,
|
|
|
218
218
|
must be between 655,360 and 8,294,400. Resolutions above 3,686,400 pixels are documented as
|
|
219
219
|
experimental by OpenAI.
|
|
220
220
|
|
|
221
|
+
To use ChatGPT/Codex subscription-backed image generation instead of the public Images API, use
|
|
222
|
+
`chatgpt-gpt-image-2`:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
const images = await generateImages({
|
|
226
|
+
model: "chatgpt-gpt-image-2",
|
|
227
|
+
stylePrompt: "Warm amber desk light, deep blue night, cinematic laboratory mood.",
|
|
228
|
+
imagePrompts: ["A compact lab bench still life with glassware and an open notebook"],
|
|
229
|
+
numImages: 1,
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
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. It returns PNG images. The
|
|
235
|
+
public Images API controls such as `imageResolution`, `imageQuality`, `outputFormat`, and
|
|
236
|
+
`outputCompression` are intentionally only on the `gpt-image-2` request type.
|
|
237
|
+
|
|
221
238
|
### Streaming (response + thoughts + usage)
|
|
222
239
|
|
|
223
240
|
```ts
|
|
@@ -495,10 +512,12 @@ console.log(result.text);
|
|
|
495
512
|
|
|
496
513
|
`gpt-5.5-fast` and `chatgpt-gpt-5.5-fast` are also supported as convenience aliases for `gpt-5.5` with priority processing enabled (`service_tier="priority"`), matching Codex `/fast` semantics.
|
|
497
514
|
|
|
498
|
-
Supported OpenAI
|
|
515
|
+
Supported OpenAI and ChatGPT model ids are fixed literal unions in code, not arbitrary strings:
|
|
499
516
|
|
|
500
|
-
- OpenAI API: `gpt-5.5`, `gpt-5.5-fast`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.4-nano`
|
|
501
|
-
-
|
|
517
|
+
- OpenAI API text: `gpt-5.5`, `gpt-5.5-fast`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.4-nano`
|
|
518
|
+
- OpenAI API image: `gpt-image-2`
|
|
519
|
+
- ChatGPT auth text: `chatgpt-gpt-5.5`, `chatgpt-gpt-5.5-fast`, `chatgpt-gpt-5.4`, `chatgpt-gpt-5.4-fast`, `chatgpt-gpt-5.4-mini`, `chatgpt-gpt-5.3-codex-spark`
|
|
520
|
+
- ChatGPT auth image: `chatgpt-gpt-image-2`
|
|
502
521
|
|
|
503
522
|
## JSON outputs
|
|
504
523
|
|
|
@@ -680,6 +699,57 @@ console.log(result.text);
|
|
|
680
699
|
|
|
681
700
|
`{ type: "shell" }` uses OpenAI hosted shell containers by default. It is only supported for OpenAI API models; ChatGPT-authenticated, Gemini, and Fireworks providers reject it.
|
|
682
701
|
|
|
702
|
+
When the shell writes artifacts under `/mnt/data`, `generateText()` returns the
|
|
703
|
+
OpenAI container reference and the library can retrieve the resulting files:
|
|
704
|
+
|
|
705
|
+
```ts
|
|
706
|
+
import { downloadOpenAiContainerFile, generateText, listOpenAiContainerFiles } from "@ljoukov/llm";
|
|
707
|
+
|
|
708
|
+
const result = await generateText({
|
|
709
|
+
model: "gpt-5.5",
|
|
710
|
+
input:
|
|
711
|
+
"Use the shell to write /mnt/data/report.txt containing 'hello'. Reply only when done.",
|
|
712
|
+
tools: [{ type: "shell" }],
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
const containerId = result.openAi?.containers.find((c) => c.toolType === "shell")?.containerId;
|
|
716
|
+
if (!containerId) throw new Error("The response did not include a hosted shell container.");
|
|
717
|
+
|
|
718
|
+
const files = await listOpenAiContainerFiles(containerId);
|
|
719
|
+
const report = files.find((file) => file.path === "/mnt/data/report.txt");
|
|
720
|
+
if (!report) throw new Error("The shell did not create report.txt.");
|
|
721
|
+
|
|
722
|
+
const bytes = await downloadOpenAiContainerFile({
|
|
723
|
+
containerId,
|
|
724
|
+
fileId: report.id,
|
|
725
|
+
});
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
For persistent multi-step shell work, create a container first, upload any input
|
|
729
|
+
assets, then pass it back as a `container-reference`:
|
|
730
|
+
|
|
731
|
+
```ts
|
|
732
|
+
import {
|
|
733
|
+
createOpenAiContainer,
|
|
734
|
+
generateText,
|
|
735
|
+
uploadOpenAiContainerFile,
|
|
736
|
+
} from "@ljoukov/llm";
|
|
737
|
+
|
|
738
|
+
const container = await createOpenAiContainer({ name: "latex-build", memoryLimit: "1g" });
|
|
739
|
+
const cover = await uploadOpenAiContainerFile({
|
|
740
|
+
containerId: container.id,
|
|
741
|
+
filename: "cover.png",
|
|
742
|
+
data: coverPngBytes,
|
|
743
|
+
mimeType: "image/png",
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
await generateText({
|
|
747
|
+
model: "gpt-5.5",
|
|
748
|
+
input: `Use ${cover.path}, write LaTeX, run xelatex, and save /mnt/data/article.pdf.`,
|
|
749
|
+
tools: [{ type: "shell", environment: { type: "container-reference", containerId: container.id } }],
|
|
750
|
+
});
|
|
751
|
+
```
|
|
752
|
+
|
|
683
753
|
### Runtime Tools (`runToolLoop()`)
|
|
684
754
|
|
|
685
755
|
Use this when the model should call your local runtime functions.
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CHATGPT_IMAGE_MODEL_IDS: () => CHATGPT_IMAGE_MODEL_IDS,
|
|
33
34
|
CHATGPT_MODEL_IDS: () => CHATGPT_MODEL_IDS,
|
|
34
35
|
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
35
36
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
@@ -83,12 +84,16 @@ __export(index_exports, {
|
|
|
83
84
|
createListDirectoryTool: () => createListDirectoryTool,
|
|
84
85
|
createModelAgnosticFilesystemToolSet: () => createModelAgnosticFilesystemToolSet,
|
|
85
86
|
createNodeAgentFilesystem: () => createNodeAgentFilesystem,
|
|
87
|
+
createOpenAiContainer: () => createOpenAiContainer,
|
|
86
88
|
createReplaceTool: () => createReplaceTool,
|
|
87
89
|
createRgSearchTool: () => createRgSearchTool,
|
|
88
90
|
createToolLoopSteeringChannel: () => createToolLoopSteeringChannel,
|
|
89
91
|
createViewImageTool: () => createViewImageTool,
|
|
90
92
|
createWriteFileTool: () => createWriteFileTool,
|
|
91
93
|
customTool: () => customTool,
|
|
94
|
+
deleteOpenAiContainer: () => deleteOpenAiContainer,
|
|
95
|
+
downloadOpenAiContainerFile: () => downloadOpenAiContainerFile,
|
|
96
|
+
downloadOpenAiContainerFileText: () => downloadOpenAiContainerFileText,
|
|
92
97
|
emptyFileUploadMetrics: () => emptyFileUploadMetrics,
|
|
93
98
|
encodeChatGptAuthJson: () => encodeChatGptAuthJson,
|
|
94
99
|
encodeChatGptAuthJsonB64: () => encodeChatGptAuthJsonB64,
|
|
@@ -101,6 +106,7 @@ __export(index_exports, {
|
|
|
101
106
|
generateText: () => generateText,
|
|
102
107
|
getChatGptAuthProfile: () => getChatGptAuthProfile,
|
|
103
108
|
getCurrentToolCallContext: () => getCurrentToolCallContext,
|
|
109
|
+
isChatGptImageModelId: () => isChatGptImageModelId,
|
|
104
110
|
isChatGptModelId: () => isChatGptModelId,
|
|
105
111
|
isExperimentalChatGptModelId: () => isExperimentalChatGptModelId,
|
|
106
112
|
isFireworksModelId: () => isFireworksModelId,
|
|
@@ -112,12 +118,14 @@ __export(index_exports, {
|
|
|
112
118
|
isLlmTextModelId: () => isLlmTextModelId,
|
|
113
119
|
isOpenAiImageModelId: () => isOpenAiImageModelId,
|
|
114
120
|
isOpenAiModelId: () => isOpenAiModelId,
|
|
121
|
+
listOpenAiContainerFiles: () => listOpenAiContainerFiles,
|
|
115
122
|
loadEnvFromFile: () => loadEnvFromFile,
|
|
116
123
|
loadLocalEnv: () => loadLocalEnv,
|
|
117
124
|
parseJsonFromLlmText: () => parseJsonFromLlmText,
|
|
118
125
|
refreshChatGptOauthToken: () => refreshChatGptOauthToken,
|
|
119
126
|
resetModelConcurrencyConfig: () => resetModelConcurrencyConfig,
|
|
120
127
|
resetTelemetry: () => resetTelemetry,
|
|
128
|
+
resolveChatGptImageProviderModel: () => resolveChatGptImageProviderModel,
|
|
121
129
|
resolveFilesystemToolProfile: () => resolveFilesystemToolProfile,
|
|
122
130
|
resolveFireworksModelId: () => resolveFireworksModelId,
|
|
123
131
|
runAgentLoop: () => runAgentLoop,
|
|
@@ -131,6 +139,7 @@ __export(index_exports, {
|
|
|
131
139
|
stripCodexCitationMarkers: () => stripCodexCitationMarkers,
|
|
132
140
|
toGeminiJsonSchema: () => toGeminiJsonSchema,
|
|
133
141
|
tool: () => tool,
|
|
142
|
+
uploadOpenAiContainerFile: () => uploadOpenAiContainerFile,
|
|
134
143
|
validateOpenAiGptImage2Resolution: () => validateOpenAiGptImage2Resolution
|
|
135
144
|
});
|
|
136
145
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -349,6 +358,10 @@ var OPENAI_IMAGE_MODEL_IDS = ["gpt-image-2"];
|
|
|
349
358
|
function isOpenAiImageModelId(value) {
|
|
350
359
|
return OPENAI_IMAGE_MODEL_IDS.includes(value);
|
|
351
360
|
}
|
|
361
|
+
var CHATGPT_IMAGE_MODEL_IDS = ["chatgpt-gpt-image-2"];
|
|
362
|
+
function isChatGptImageModelId(value) {
|
|
363
|
+
return CHATGPT_IMAGE_MODEL_IDS.includes(value);
|
|
364
|
+
}
|
|
352
365
|
var OPENAI_GPT_IMAGE_2_POPULAR_RESOLUTIONS = [
|
|
353
366
|
"1024x1024",
|
|
354
367
|
"1536x1024",
|
|
@@ -431,6 +444,7 @@ var CHATGPT_MODEL_IDS = [
|
|
|
431
444
|
var FAST_MODEL_SUFFIX = "-fast";
|
|
432
445
|
var OPENAI_PRIORITY_MODEL_IDS = ["gpt-5.5-fast"];
|
|
433
446
|
var CHATGPT_PRIORITY_MODEL_IDS = ["chatgpt-gpt-5.5-fast", "chatgpt-gpt-5.4-fast"];
|
|
447
|
+
var CHATGPT_IMAGE_GENERATION_PROVIDER_MODEL = "gpt-5.4";
|
|
434
448
|
var EXPERIMENTAL_CHATGPT_MODEL_PREFIX = "experimental-chatgpt-";
|
|
435
449
|
function isExperimentalChatGptModelId(value) {
|
|
436
450
|
return value.startsWith(EXPERIMENTAL_CHATGPT_MODEL_PREFIX) && value.length > EXPERIMENTAL_CHATGPT_MODEL_PREFIX.length;
|
|
@@ -457,6 +471,9 @@ function resolveChatGptProviderModel(model) {
|
|
|
457
471
|
const providerModel = stripChatGptPrefix(model);
|
|
458
472
|
return CHATGPT_PRIORITY_MODEL_IDS.includes(model) ? stripFastSuffix(providerModel) : providerModel;
|
|
459
473
|
}
|
|
474
|
+
function resolveChatGptImageProviderModel(_model) {
|
|
475
|
+
return CHATGPT_IMAGE_GENERATION_PROVIDER_MODEL;
|
|
476
|
+
}
|
|
460
477
|
function resolveChatGptServiceTier(model) {
|
|
461
478
|
return CHATGPT_PRIORITY_MODEL_IDS.includes(model) ? "priority" : void 0;
|
|
462
479
|
}
|
|
@@ -551,7 +568,7 @@ function getOpenAiPricing(modelId) {
|
|
|
551
568
|
return void 0;
|
|
552
569
|
}
|
|
553
570
|
function getOpenAiImagePricing(modelId) {
|
|
554
|
-
return isOpenAiImageModelId(modelId) ? OPENAI_GPT_IMAGE_2_PRICING : void 0;
|
|
571
|
+
return isOpenAiImageModelId(modelId) || isChatGptImageModelId(modelId) ? OPENAI_GPT_IMAGE_2_PRICING : void 0;
|
|
555
572
|
}
|
|
556
573
|
|
|
557
574
|
// src/utils/cost.ts
|
|
@@ -1826,6 +1843,8 @@ async function collectChatGptCodexStream(options) {
|
|
|
1826
1843
|
const toolCallOrder = [];
|
|
1827
1844
|
const webSearchCalls = /* @__PURE__ */ new Map();
|
|
1828
1845
|
const webSearchCallOrder = [];
|
|
1846
|
+
const imageGenerationCalls = /* @__PURE__ */ new Map();
|
|
1847
|
+
const imageGenerationCallOrder = [];
|
|
1829
1848
|
let text = "";
|
|
1830
1849
|
const reasoningText = "";
|
|
1831
1850
|
let reasoningSummaryText = "";
|
|
@@ -1896,6 +1915,20 @@ async function collectChatGptCodexStream(options) {
|
|
|
1896
1915
|
action: item.action && typeof item.action === "object" ? item.action : void 0
|
|
1897
1916
|
});
|
|
1898
1917
|
}
|
|
1918
|
+
} else if (item.type === "image_generation_call") {
|
|
1919
|
+
const id = typeof item.id === "string" ? item.id : "";
|
|
1920
|
+
const result = typeof item.result === "string" ? item.result : "";
|
|
1921
|
+
if (id && result) {
|
|
1922
|
+
if (!imageGenerationCalls.has(id)) {
|
|
1923
|
+
imageGenerationCallOrder.push(id);
|
|
1924
|
+
}
|
|
1925
|
+
imageGenerationCalls.set(id, {
|
|
1926
|
+
id,
|
|
1927
|
+
status: typeof item.status === "string" ? item.status : void 0,
|
|
1928
|
+
revisedPrompt: typeof item.revised_prompt === "string" ? item.revised_prompt : void 0,
|
|
1929
|
+
result
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1899
1932
|
}
|
|
1900
1933
|
}
|
|
1901
1934
|
continue;
|
|
@@ -1935,12 +1968,14 @@ async function collectChatGptCodexStream(options) {
|
|
|
1935
1968
|
}
|
|
1936
1969
|
const orderedToolCalls = toolCallOrder.map((id) => toolCalls.get(id)).filter((call) => call !== void 0);
|
|
1937
1970
|
const orderedWebSearchCalls = webSearchCallOrder.map((id) => webSearchCalls.get(id)).filter((call) => call !== void 0);
|
|
1971
|
+
const orderedImageGenerationCalls = imageGenerationCallOrder.map((id) => imageGenerationCalls.get(id)).filter((call) => call !== void 0);
|
|
1938
1972
|
return {
|
|
1939
1973
|
text,
|
|
1940
1974
|
reasoningText,
|
|
1941
1975
|
reasoningSummaryText,
|
|
1942
1976
|
toolCalls: orderedToolCalls,
|
|
1943
1977
|
webSearchCalls: orderedWebSearchCalls,
|
|
1978
|
+
imageGenerationCalls: orderedImageGenerationCalls,
|
|
1944
1979
|
usage,
|
|
1945
1980
|
id: responseId,
|
|
1946
1981
|
model,
|
|
@@ -4652,13 +4687,17 @@ var LLM_TEXT_MODEL_IDS = [
|
|
|
4652
4687
|
...FIREWORKS_MODEL_IDS,
|
|
4653
4688
|
...GEMINI_TEXT_MODEL_IDS
|
|
4654
4689
|
];
|
|
4655
|
-
var LLM_IMAGE_MODEL_IDS = [
|
|
4690
|
+
var LLM_IMAGE_MODEL_IDS = [
|
|
4691
|
+
...OPENAI_IMAGE_MODEL_IDS,
|
|
4692
|
+
...CHATGPT_IMAGE_MODEL_IDS,
|
|
4693
|
+
...GEMINI_IMAGE_MODEL_IDS
|
|
4694
|
+
];
|
|
4656
4695
|
var LLM_MODEL_IDS = [...LLM_TEXT_MODEL_IDS, ...LLM_IMAGE_MODEL_IDS];
|
|
4657
4696
|
function isLlmTextModelId(value) {
|
|
4658
4697
|
return isOpenAiModelId(value) || isChatGptModelId(value) || isFireworksModelId(value) || isGeminiTextModelId(value);
|
|
4659
4698
|
}
|
|
4660
4699
|
function isLlmImageModelId(value) {
|
|
4661
|
-
return isOpenAiImageModelId(value) || isGeminiImageModelId(value);
|
|
4700
|
+
return isOpenAiImageModelId(value) || isChatGptImageModelId(value) || isGeminiImageModelId(value);
|
|
4662
4701
|
}
|
|
4663
4702
|
function isLlmModelId(value) {
|
|
4664
4703
|
return isLlmTextModelId(value) || isLlmImageModelId(value);
|
|
@@ -4673,6 +4712,9 @@ var LlmJsonCallError = class extends Error {
|
|
|
4673
4712
|
function isOpenAiGenerateImagesRequest(request) {
|
|
4674
4713
|
return isOpenAiImageModelId(request.model);
|
|
4675
4714
|
}
|
|
4715
|
+
function isChatGptGenerateImagesRequest(request) {
|
|
4716
|
+
return isChatGptImageModelId(request.model);
|
|
4717
|
+
}
|
|
4676
4718
|
function tool(options) {
|
|
4677
4719
|
return {
|
|
4678
4720
|
type: "function",
|
|
@@ -5266,6 +5308,12 @@ function resolveProvider(model) {
|
|
|
5266
5308
|
if (isOpenAiImageModelId(model)) {
|
|
5267
5309
|
return { provider: "openai", model };
|
|
5268
5310
|
}
|
|
5311
|
+
if (isChatGptImageModelId(model)) {
|
|
5312
|
+
return {
|
|
5313
|
+
provider: "chatgpt",
|
|
5314
|
+
model: resolveChatGptImageProviderModel(model)
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5269
5317
|
if (isOpenAiModelId(model)) {
|
|
5270
5318
|
return {
|
|
5271
5319
|
provider: "openai",
|
|
@@ -6420,6 +6468,50 @@ function toOpenAiTools(tools, options) {
|
|
|
6420
6468
|
}
|
|
6421
6469
|
});
|
|
6422
6470
|
}
|
|
6471
|
+
function extractOpenAiResponseMetadata(response) {
|
|
6472
|
+
if (!response || typeof response !== "object") {
|
|
6473
|
+
return void 0;
|
|
6474
|
+
}
|
|
6475
|
+
const record = response;
|
|
6476
|
+
const responseId = typeof record.id === "string" ? record.id : void 0;
|
|
6477
|
+
const output = Array.isArray(record.output) ? record.output : [];
|
|
6478
|
+
const containers = [];
|
|
6479
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6480
|
+
const addContainer = (container) => {
|
|
6481
|
+
const key = `${container.toolType}:${container.containerId}:${container.itemId ?? ""}:${container.callId ?? ""}`;
|
|
6482
|
+
if (seen.has(key)) {
|
|
6483
|
+
return;
|
|
6484
|
+
}
|
|
6485
|
+
seen.add(key);
|
|
6486
|
+
containers.push(container);
|
|
6487
|
+
};
|
|
6488
|
+
for (const item of output) {
|
|
6489
|
+
if (!item || typeof item !== "object") {
|
|
6490
|
+
continue;
|
|
6491
|
+
}
|
|
6492
|
+
const itemRecord = item;
|
|
6493
|
+
const itemId = typeof itemRecord.id === "string" ? itemRecord.id : void 0;
|
|
6494
|
+
const callId = typeof itemRecord.call_id === "string" ? itemRecord.call_id : void 0;
|
|
6495
|
+
if (itemRecord.type === "shell_call") {
|
|
6496
|
+
const environment = itemRecord.environment && typeof itemRecord.environment === "object" ? itemRecord.environment : void 0;
|
|
6497
|
+
const containerId = environment?.type === "container_reference" && typeof environment.container_id === "string" ? environment.container_id : void 0;
|
|
6498
|
+
if (containerId) {
|
|
6499
|
+
addContainer({ containerId, toolType: "shell", itemId, callId });
|
|
6500
|
+
}
|
|
6501
|
+
continue;
|
|
6502
|
+
}
|
|
6503
|
+
if (itemRecord.type === "code_interpreter_call") {
|
|
6504
|
+
const containerId = typeof itemRecord.container_id === "string" ? itemRecord.container_id : void 0;
|
|
6505
|
+
if (containerId) {
|
|
6506
|
+
addContainer({ containerId, toolType: "code_interpreter", itemId, callId });
|
|
6507
|
+
}
|
|
6508
|
+
}
|
|
6509
|
+
}
|
|
6510
|
+
if (!responseId && containers.length === 0) {
|
|
6511
|
+
return void 0;
|
|
6512
|
+
}
|
|
6513
|
+
return { ...responseId ? { responseId } : {}, containers };
|
|
6514
|
+
}
|
|
6423
6515
|
function mergeTokenUpdates(current, next) {
|
|
6424
6516
|
if (!next) {
|
|
6425
6517
|
return current;
|
|
@@ -8031,6 +8123,7 @@ async function runTextCall(params) {
|
|
|
8031
8123
|
let modelVersion = request.model;
|
|
8032
8124
|
let blocked = false;
|
|
8033
8125
|
let grounding;
|
|
8126
|
+
let openAi;
|
|
8034
8127
|
const responseParts = [];
|
|
8035
8128
|
let responseRole;
|
|
8036
8129
|
let latestUsage;
|
|
@@ -8141,6 +8234,7 @@ async function runTextCall(params) {
|
|
|
8141
8234
|
}
|
|
8142
8235
|
}
|
|
8143
8236
|
const finalResponse = await stream.finalResponse();
|
|
8237
|
+
openAi = extractOpenAiResponseMetadata(finalResponse);
|
|
8144
8238
|
modelVersion = typeof finalResponse.model === "string" ? finalResponse.model : request.model;
|
|
8145
8239
|
pushEvent({ type: "model", modelVersion });
|
|
8146
8240
|
if (finalResponse.error) {
|
|
@@ -8172,6 +8266,11 @@ async function runTextCall(params) {
|
|
|
8172
8266
|
}
|
|
8173
8267
|
}, modelForProvider);
|
|
8174
8268
|
} else if (provider === "chatgpt") {
|
|
8269
|
+
if (isChatGptImageModelId(request.model)) {
|
|
8270
|
+
throw new Error(
|
|
8271
|
+
"chatgpt-gpt-image-2 is an image generation model; use generateImages()."
|
|
8272
|
+
);
|
|
8273
|
+
}
|
|
8175
8274
|
const chatGptInput = toChatGptInput(contents, {
|
|
8176
8275
|
defaultMediaResolution: request.mediaResolution,
|
|
8177
8276
|
model: request.model
|
|
@@ -8379,6 +8478,7 @@ async function runTextCall(params) {
|
|
|
8379
8478
|
costUsd,
|
|
8380
8479
|
usage: latestUsage,
|
|
8381
8480
|
grounding: grounding ? sanitiseLogValue(grounding) : void 0,
|
|
8481
|
+
openAi: openAi ? sanitiseLogValue(openAi) : void 0,
|
|
8382
8482
|
responseChars: text.length,
|
|
8383
8483
|
thoughtChars: thoughts.length,
|
|
8384
8484
|
responseImages,
|
|
@@ -8395,7 +8495,8 @@ async function runTextCall(params) {
|
|
|
8395
8495
|
blocked,
|
|
8396
8496
|
usage: latestUsage,
|
|
8397
8497
|
costUsd,
|
|
8398
|
-
grounding
|
|
8498
|
+
grounding,
|
|
8499
|
+
openAi
|
|
8399
8500
|
};
|
|
8400
8501
|
} catch (error) {
|
|
8401
8502
|
const partialParts = mergeConsecutiveTextParts(responseParts);
|
|
@@ -10625,10 +10726,144 @@ async function generateImagesWithOpenAiImageApi(request) {
|
|
|
10625
10726
|
await telemetry.flush();
|
|
10626
10727
|
}
|
|
10627
10728
|
}
|
|
10729
|
+
function buildChatGptImageInputContent(params) {
|
|
10730
|
+
const parts = [
|
|
10731
|
+
{
|
|
10732
|
+
type: "text",
|
|
10733
|
+
text: params.prompt
|
|
10734
|
+
}
|
|
10735
|
+
];
|
|
10736
|
+
for (const [index, image] of (params.styleImages ?? []).entries()) {
|
|
10737
|
+
const mimeType = image.mimeType ?? "image/png";
|
|
10738
|
+
parts.push({
|
|
10739
|
+
type: "inlineData",
|
|
10740
|
+
data: image.data.toString("base64"),
|
|
10741
|
+
mimeType,
|
|
10742
|
+
filename: `style-${index + 1}.${resolveAttachmentExtension(mimeType)}`
|
|
10743
|
+
});
|
|
10744
|
+
}
|
|
10745
|
+
return [{ role: "user", parts }];
|
|
10746
|
+
}
|
|
10747
|
+
async function generateImagesWithChatGptImageTool(request) {
|
|
10748
|
+
const promptEntries = Array.from(request.imagePrompts, (rawPrompt, index) => {
|
|
10749
|
+
const prompt = rawPrompt.trim();
|
|
10750
|
+
if (!prompt) {
|
|
10751
|
+
throw new Error(`imagePrompts[${index}] must be a non-empty string`);
|
|
10752
|
+
}
|
|
10753
|
+
return prompt;
|
|
10754
|
+
});
|
|
10755
|
+
if (promptEntries.length === 0) {
|
|
10756
|
+
return [];
|
|
10757
|
+
}
|
|
10758
|
+
const providerInfo = resolveProvider(request.model);
|
|
10759
|
+
const telemetry = createLlmTelemetryEmitter({
|
|
10760
|
+
telemetry: request.telemetry,
|
|
10761
|
+
operation: "generateImages",
|
|
10762
|
+
provider: providerInfo.provider,
|
|
10763
|
+
model: request.model
|
|
10764
|
+
});
|
|
10765
|
+
const startedAtMs = Date.now();
|
|
10766
|
+
const numImagesPerPrompt = request.numImages ?? 1;
|
|
10767
|
+
let totalUsage;
|
|
10768
|
+
let costUsd = 0;
|
|
10769
|
+
let outputImages = 0;
|
|
10770
|
+
telemetry.emit({
|
|
10771
|
+
type: "llm.call.started",
|
|
10772
|
+
imagePromptCount: promptEntries.length,
|
|
10773
|
+
styleImageCount: request.styleImages?.length ?? 0,
|
|
10774
|
+
numImagesPerPrompt
|
|
10775
|
+
});
|
|
10776
|
+
try {
|
|
10777
|
+
const images = [];
|
|
10778
|
+
for (const imagePrompt of promptEntries) {
|
|
10779
|
+
const prompt = buildOpenAiImagePrompt({
|
|
10780
|
+
stylePrompt: request.stylePrompt,
|
|
10781
|
+
imagePrompt,
|
|
10782
|
+
hasStyleImages: Boolean(request.styleImages && request.styleImages.length > 0)
|
|
10783
|
+
});
|
|
10784
|
+
for (let imageIndex = 0; imageIndex < numImagesPerPrompt; imageIndex += 1) {
|
|
10785
|
+
const chatGptInput = toChatGptInput(
|
|
10786
|
+
buildChatGptImageInputContent({
|
|
10787
|
+
prompt,
|
|
10788
|
+
styleImages: request.styleImages
|
|
10789
|
+
}),
|
|
10790
|
+
{ model: request.model }
|
|
10791
|
+
);
|
|
10792
|
+
const preparedInput = await maybePrepareOpenAiPromptInput(chatGptInput.input, {
|
|
10793
|
+
model: request.model,
|
|
10794
|
+
provider: "chatgpt"
|
|
10795
|
+
});
|
|
10796
|
+
const result = await collectChatGptCodexResponseWithRetry({
|
|
10797
|
+
request: {
|
|
10798
|
+
model: providerInfo.model,
|
|
10799
|
+
store: false,
|
|
10800
|
+
stream: true,
|
|
10801
|
+
instructions: chatGptInput.instructions ?? "Use the image_generation tool to generate exactly one PNG image. Do not return prose instead of the image.",
|
|
10802
|
+
input: preparedInput,
|
|
10803
|
+
tool_choice: "required",
|
|
10804
|
+
parallel_tool_calls: false,
|
|
10805
|
+
tools: [{ type: "image_generation", output_format: "png" }]
|
|
10806
|
+
},
|
|
10807
|
+
signal: request.signal
|
|
10808
|
+
});
|
|
10809
|
+
if (result.status && result.status !== "completed") {
|
|
10810
|
+
throw new Error(`ChatGPT image generation response status ${result.status}`);
|
|
10811
|
+
}
|
|
10812
|
+
if (result.imageGenerationCalls.length === 0) {
|
|
10813
|
+
throw new Error("ChatGPT image generation returned no image_generation_call result.");
|
|
10814
|
+
}
|
|
10815
|
+
for (const call of result.imageGenerationCalls) {
|
|
10816
|
+
images.push({
|
|
10817
|
+
mimeType: "image/png",
|
|
10818
|
+
data: import_node_buffer4.Buffer.from(call.result, "base64")
|
|
10819
|
+
});
|
|
10820
|
+
}
|
|
10821
|
+
outputImages = images.length;
|
|
10822
|
+
const usage = extractChatGptUsageTokens(result.usage);
|
|
10823
|
+
totalUsage = sumUsageTokens(totalUsage, usage);
|
|
10824
|
+
costUsd += estimateCallCostUsd({
|
|
10825
|
+
modelId: request.model,
|
|
10826
|
+
tokens: usage,
|
|
10827
|
+
responseImages: result.imageGenerationCalls.length,
|
|
10828
|
+
imageSize: "1024x1024",
|
|
10829
|
+
imageQuality: "medium"
|
|
10830
|
+
});
|
|
10831
|
+
}
|
|
10832
|
+
}
|
|
10833
|
+
telemetry.emit({
|
|
10834
|
+
type: "llm.call.completed",
|
|
10835
|
+
success: true,
|
|
10836
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
10837
|
+
modelVersion: request.model,
|
|
10838
|
+
usage: totalUsage,
|
|
10839
|
+
costUsd,
|
|
10840
|
+
imageCount: images.length,
|
|
10841
|
+
attempts: promptEntries.length * numImagesPerPrompt
|
|
10842
|
+
});
|
|
10843
|
+
return images;
|
|
10844
|
+
} catch (error) {
|
|
10845
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
10846
|
+
telemetry.emit({
|
|
10847
|
+
type: "llm.call.completed",
|
|
10848
|
+
success: false,
|
|
10849
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
10850
|
+
usage: totalUsage,
|
|
10851
|
+
costUsd,
|
|
10852
|
+
imageCount: outputImages,
|
|
10853
|
+
error: err.message
|
|
10854
|
+
});
|
|
10855
|
+
throw err;
|
|
10856
|
+
} finally {
|
|
10857
|
+
await telemetry.flush();
|
|
10858
|
+
}
|
|
10859
|
+
}
|
|
10628
10860
|
async function generateImages(request) {
|
|
10629
10861
|
if (isOpenAiGenerateImagesRequest(request)) {
|
|
10630
10862
|
return await generateImagesWithOpenAiImageApi(request);
|
|
10631
10863
|
}
|
|
10864
|
+
if (isChatGptGenerateImagesRequest(request)) {
|
|
10865
|
+
return await generateImagesWithChatGptImageTool(request);
|
|
10866
|
+
}
|
|
10632
10867
|
const maxAttempts = Math.max(1, Math.floor(request.maxAttempts ?? 4));
|
|
10633
10868
|
const promptList = Array.from(request.imagePrompts);
|
|
10634
10869
|
if (promptList.length === 0) {
|
|
@@ -10910,6 +11145,104 @@ function appendMarkdownSourcesSection(value, sources) {
|
|
|
10910
11145
|
${lines}`;
|
|
10911
11146
|
}
|
|
10912
11147
|
|
|
11148
|
+
// src/openai/containers.ts
|
|
11149
|
+
var import_openai4 = require("openai");
|
|
11150
|
+
function toOpenAiContainerNetworkPolicy(policy) {
|
|
11151
|
+
if (!policy) {
|
|
11152
|
+
return void 0;
|
|
11153
|
+
}
|
|
11154
|
+
if (policy.type === "disabled") {
|
|
11155
|
+
return { type: "disabled" };
|
|
11156
|
+
}
|
|
11157
|
+
return {
|
|
11158
|
+
type: "allowlist",
|
|
11159
|
+
allowed_domains: Array.from(policy.allowedDomains),
|
|
11160
|
+
...policy.domainSecrets ? {
|
|
11161
|
+
domain_secrets: policy.domainSecrets.map((secret) => ({
|
|
11162
|
+
domain: secret.domain,
|
|
11163
|
+
name: secret.name,
|
|
11164
|
+
value: secret.value
|
|
11165
|
+
}))
|
|
11166
|
+
} : {}
|
|
11167
|
+
};
|
|
11168
|
+
}
|
|
11169
|
+
function toContainer(container) {
|
|
11170
|
+
return {
|
|
11171
|
+
id: String(container.id),
|
|
11172
|
+
name: typeof container.name === "string" ? container.name : "",
|
|
11173
|
+
status: typeof container.status === "string" ? container.status : "",
|
|
11174
|
+
...typeof container.created_at === "number" ? { createdAt: container.created_at } : {},
|
|
11175
|
+
...typeof container.last_active_at === "number" ? { lastActiveAt: container.last_active_at } : {},
|
|
11176
|
+
...typeof container.memory_limit === "string" ? { memoryLimit: container.memory_limit } : {}
|
|
11177
|
+
};
|
|
11178
|
+
}
|
|
11179
|
+
function toContainerFile(file) {
|
|
11180
|
+
return {
|
|
11181
|
+
id: String(file.id),
|
|
11182
|
+
containerId: typeof file.container_id === "string" ? file.container_id : "",
|
|
11183
|
+
path: typeof file.path === "string" ? file.path : "",
|
|
11184
|
+
...typeof file.bytes === "number" || file.bytes === null ? { bytes: file.bytes } : {},
|
|
11185
|
+
...typeof file.created_at === "number" ? { createdAt: file.created_at } : {},
|
|
11186
|
+
...typeof file.source === "string" ? { source: file.source } : {}
|
|
11187
|
+
};
|
|
11188
|
+
}
|
|
11189
|
+
async function createOpenAiContainer(options) {
|
|
11190
|
+
const container = await runOpenAiCall(
|
|
11191
|
+
async (client) => await client.containers.create({
|
|
11192
|
+
name: options.name,
|
|
11193
|
+
...options.fileIds ? { file_ids: Array.from(options.fileIds) } : {},
|
|
11194
|
+
...options.memoryLimit ? { memory_limit: options.memoryLimit } : {},
|
|
11195
|
+
...options.networkPolicy ? { network_policy: toOpenAiContainerNetworkPolicy(options.networkPolicy) } : {},
|
|
11196
|
+
...options.expiresAfterMinutes ? {
|
|
11197
|
+
expires_after: {
|
|
11198
|
+
anchor: "last_active_at",
|
|
11199
|
+
minutes: options.expiresAfterMinutes
|
|
11200
|
+
}
|
|
11201
|
+
} : {}
|
|
11202
|
+
}),
|
|
11203
|
+
"openai-containers"
|
|
11204
|
+
);
|
|
11205
|
+
return toContainer(container);
|
|
11206
|
+
}
|
|
11207
|
+
async function deleteOpenAiContainer(containerId) {
|
|
11208
|
+
await runOpenAiCall(
|
|
11209
|
+
async (client) => await client.containers.delete(containerId),
|
|
11210
|
+
"openai-containers"
|
|
11211
|
+
);
|
|
11212
|
+
}
|
|
11213
|
+
async function listOpenAiContainerFiles(containerId) {
|
|
11214
|
+
const files2 = [];
|
|
11215
|
+
await runOpenAiCall(async (client) => {
|
|
11216
|
+
for await (const file of client.containers.files.list(containerId)) {
|
|
11217
|
+
files2.push(toContainerFile(file));
|
|
11218
|
+
}
|
|
11219
|
+
}, "openai-containers");
|
|
11220
|
+
return files2;
|
|
11221
|
+
}
|
|
11222
|
+
async function uploadOpenAiContainerFile(upload) {
|
|
11223
|
+
const file = await (0, import_openai4.toFile)(upload.data, upload.filename, {
|
|
11224
|
+
...upload.mimeType ? { type: upload.mimeType } : {}
|
|
11225
|
+
});
|
|
11226
|
+
const created = await runOpenAiCall(
|
|
11227
|
+
async (client) => await client.containers.files.create(upload.containerId, { file }),
|
|
11228
|
+
"openai-containers"
|
|
11229
|
+
);
|
|
11230
|
+
return toContainerFile(created);
|
|
11231
|
+
}
|
|
11232
|
+
async function downloadOpenAiContainerFile(params) {
|
|
11233
|
+
const response = await runOpenAiCall(
|
|
11234
|
+
async (client) => await client.containers.files.content.retrieve(params.fileId, {
|
|
11235
|
+
container_id: params.containerId
|
|
11236
|
+
}),
|
|
11237
|
+
"openai-containers"
|
|
11238
|
+
);
|
|
11239
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
11240
|
+
}
|
|
11241
|
+
async function downloadOpenAiContainerFileText(params) {
|
|
11242
|
+
const bytes = await downloadOpenAiContainerFile(params);
|
|
11243
|
+
return new TextDecoder().decode(bytes);
|
|
11244
|
+
}
|
|
11245
|
+
|
|
10913
11246
|
// src/agent.ts
|
|
10914
11247
|
var import_node_crypto4 = require("crypto");
|
|
10915
11248
|
var import_node_path9 = __toESM(require("path"), 1);
|
|
@@ -14656,6 +14989,7 @@ async function runCandidateEvolution(options) {
|
|
|
14656
14989
|
}
|
|
14657
14990
|
// Annotate the CommonJS export names for ESM import in node:
|
|
14658
14991
|
0 && (module.exports = {
|
|
14992
|
+
CHATGPT_IMAGE_MODEL_IDS,
|
|
14659
14993
|
CHATGPT_MODEL_IDS,
|
|
14660
14994
|
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
14661
14995
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
@@ -14709,12 +15043,16 @@ async function runCandidateEvolution(options) {
|
|
|
14709
15043
|
createListDirectoryTool,
|
|
14710
15044
|
createModelAgnosticFilesystemToolSet,
|
|
14711
15045
|
createNodeAgentFilesystem,
|
|
15046
|
+
createOpenAiContainer,
|
|
14712
15047
|
createReplaceTool,
|
|
14713
15048
|
createRgSearchTool,
|
|
14714
15049
|
createToolLoopSteeringChannel,
|
|
14715
15050
|
createViewImageTool,
|
|
14716
15051
|
createWriteFileTool,
|
|
14717
15052
|
customTool,
|
|
15053
|
+
deleteOpenAiContainer,
|
|
15054
|
+
downloadOpenAiContainerFile,
|
|
15055
|
+
downloadOpenAiContainerFileText,
|
|
14718
15056
|
emptyFileUploadMetrics,
|
|
14719
15057
|
encodeChatGptAuthJson,
|
|
14720
15058
|
encodeChatGptAuthJsonB64,
|
|
@@ -14727,6 +15065,7 @@ async function runCandidateEvolution(options) {
|
|
|
14727
15065
|
generateText,
|
|
14728
15066
|
getChatGptAuthProfile,
|
|
14729
15067
|
getCurrentToolCallContext,
|
|
15068
|
+
isChatGptImageModelId,
|
|
14730
15069
|
isChatGptModelId,
|
|
14731
15070
|
isExperimentalChatGptModelId,
|
|
14732
15071
|
isFireworksModelId,
|
|
@@ -14738,12 +15077,14 @@ async function runCandidateEvolution(options) {
|
|
|
14738
15077
|
isLlmTextModelId,
|
|
14739
15078
|
isOpenAiImageModelId,
|
|
14740
15079
|
isOpenAiModelId,
|
|
15080
|
+
listOpenAiContainerFiles,
|
|
14741
15081
|
loadEnvFromFile,
|
|
14742
15082
|
loadLocalEnv,
|
|
14743
15083
|
parseJsonFromLlmText,
|
|
14744
15084
|
refreshChatGptOauthToken,
|
|
14745
15085
|
resetModelConcurrencyConfig,
|
|
14746
15086
|
resetTelemetry,
|
|
15087
|
+
resolveChatGptImageProviderModel,
|
|
14747
15088
|
resolveFilesystemToolProfile,
|
|
14748
15089
|
resolveFireworksModelId,
|
|
14749
15090
|
runAgentLoop,
|
|
@@ -14757,6 +15098,7 @@ async function runCandidateEvolution(options) {
|
|
|
14757
15098
|
stripCodexCitationMarkers,
|
|
14758
15099
|
toGeminiJsonSchema,
|
|
14759
15100
|
tool,
|
|
15101
|
+
uploadOpenAiContainerFile,
|
|
14760
15102
|
validateOpenAiGptImage2Resolution
|
|
14761
15103
|
});
|
|
14762
15104
|
//# sourceMappingURL=index.cjs.map
|