ima2-gen 3.16.1 → 3.17.0
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 +29 -0
- package/bin/commands/edit.js +6 -2
- package/bin/commands/gen.js +7 -2
- package/bin/commands/multimode.js +6 -2
- package/bin/commands/node.js +5 -0
- package/bin/lib/error-hints.js +1 -1
- package/bin/lib/model-aliases.js +1 -0
- package/docs/API.md +13 -0
- package/docs/CLI.md +14 -0
- package/docs/FAQ.ko.md +1 -0
- package/docs/FAQ.md +1 -0
- package/docs/FAQ.zh-CN.md +1 -0
- package/docs/FAQ.zh-TW.md +1 -0
- package/docs/README.ja.md +1 -0
- package/docs/README.ko.md +1 -0
- package/docs/README.zh-CN.md +1 -0
- package/docs/README.zh-TW.md +1 -0
- package/docs/migration/runtime-test-inventory.md +10 -1
- package/integrations/comfyui/ima2_gen_bridge/nodes.py +1 -1
- package/lib/capabilities.js +2 -1
- package/lib/generatePipeline.js +9 -3
- package/lib/historyList.js +1 -0
- package/lib/imageMetadata.js +1 -0
- package/lib/imageModels.js +18 -1
- package/lib/multimodePipeline.js +11 -3
- package/lib/nodeGeneration.js +9 -3
- package/lib/oauthNormalize.js +22 -3
- package/lib/promptBuilder/constants.js +1 -1
- package/lib/providerOptions.js +11 -3
- package/lib/providers/adapters/openaiExecution.js +7 -7
- package/lib/providers/adapters/openaiOperations.js +22 -3
- package/lib/providers/registry.js +2 -0
- package/package.json +3 -2
- package/routes/edit.js +9 -3
- package/ui/dist/.vite/manifest.json +61 -61
- package/ui/dist/assets/AgentWorkspace-DdQ7EVuV.js +3 -0
- package/ui/dist/assets/App-lx7RIWUB.js +9 -0
- package/ui/dist/assets/{AssetGenWorkspace-C8eIs-bS.js → AssetGenWorkspace-9cFuwMY0.js} +2 -2
- package/ui/dist/assets/{AssetsWorkspace-BcbAM8uC.js → AssetsWorkspace--OGFfh8y.js} +1 -1
- package/ui/dist/assets/{CardNewsWorkspace-CM5hwbRV.js → CardNewsWorkspace-CDLRdair.js} +1 -1
- package/ui/dist/assets/{GenerationRequestLogPanel-CTs8OymS.js → GenerationRequestLogPanel-BmhuuHj-.js} +1 -1
- package/ui/dist/assets/{HomeWorkspace-KGUtIZyG.js → HomeWorkspace-Dzkva2Mr.js} +1 -1
- package/ui/dist/assets/{KeyingPanel-D8ZHmWcC.js → KeyingPanel-YsPilwZ1.js} +1 -1
- package/ui/dist/assets/{NodeCanvas-D2N3m-1s.js → NodeCanvas-BqkCtDtr.js} +1 -1
- package/ui/dist/assets/{PromptBuilderPanel-BolZnOa7.js → PromptBuilderPanel-d_g5JLDo.js} +1 -1
- package/ui/dist/assets/{PromptImportDialog-DBpe7Vkj.js → PromptImportDialog-CqG-vRqd.js} +2 -2
- package/ui/dist/assets/{PromptImportDiscoverySection-Dk6v6lUZ.js → PromptImportDiscoverySection-DdkPKdK7.js} +1 -1
- package/ui/dist/assets/{PromptImportFolderSection-BE7Nfq9Y.js → PromptImportFolderSection-Bi3Uve7i.js} +1 -1
- package/ui/dist/assets/{PromptLibraryPanel-Qdujpb4L.js → PromptLibraryPanel-ByIAu1g9.js} +2 -2
- package/ui/dist/assets/{SettingsWorkspace-Dm4wezu_.js → SettingsWorkspace-_ND9Fgfz.js} +1 -1
- package/ui/dist/assets/{SpriteRecipeWorkspace-D9do9V7F.js → SpriteRecipeWorkspace-B8sLq0Nn.js} +1 -1
- package/ui/dist/assets/index-BL_H_Z8O.css +1 -0
- package/ui/dist/assets/{index-CfGRmfFv.js → index-Bl__p_6_.js} +7 -7
- package/ui/dist/assets/index-DZNGW1wK.js +5 -0
- package/ui/dist/assets/{pptxgen.es-BLI_YKez.js → pptxgen.es-DZuurLP8.js} +1 -1
- package/ui/dist/assets/{promptBuilderStore-BMiudG9n.js → promptBuilderStore-2KCBiZVN.js} +1 -1
- package/ui/dist/assets/useAgentDialogFocus-BPzq1JAp.js +1 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/AgentWorkspace-DlLaTsPK.js +0 -3
- package/ui/dist/assets/App-BfpvLzSs.js +0 -9
- package/ui/dist/assets/index-CfrOcJIe.js +0 -5
- package/ui/dist/assets/index-D0NhOovz.css +0 -1
- package/ui/dist/assets/useAgentDialogFocus-CCj5EYE9.js +0 -1
package/lib/nodeGeneration.js
CHANGED
|
@@ -41,9 +41,9 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
41
41
|
const cancelController = new AbortController();
|
|
42
42
|
const referencePayload = summarizeReferencePayload(body.references);
|
|
43
43
|
try {
|
|
44
|
-
const { prompt: rawPrompt, quality: rawQuality = "medium", size = "1024x1024", format = "png", moderation = "low", references = [], externalSrc = null, mode: promptMode = "auto", contextMode: rawContextMode = "parent-plus-refs", searchMode: rawSearchMode = "on", model: rawModel, reasoningEffort: rawReasoningEffort, } = body;
|
|
44
|
+
const { prompt: rawPrompt, quality: rawQuality = "medium", size = "1024x1024", format = "png", moderation = "low", references = [], externalSrc = null, mode: promptMode = "auto", contextMode: rawContextMode = "parent-plus-refs", searchMode: rawSearchMode = "on", model: rawModel, imageToolModel: rawImageToolModel, reasoningEffort: rawReasoningEffort, } = body;
|
|
45
45
|
const { provider = "oauth" } = body;
|
|
46
|
-
const { quality, warnings: qualityWarnings } = normalizeOAuthParams({ provider, quality: rawQuality });
|
|
46
|
+
const { quality, warnings: qualityWarnings } = normalizeOAuthParams({ provider, quality: rawQuality, imageToolModel: rawImageToolModel });
|
|
47
47
|
const normalizedPromptMode = promptMode === "direct" ? "direct" : "auto";
|
|
48
48
|
const contextMode = rawContextMode === "parent-only" ? "parent-only"
|
|
49
49
|
: rawContextMode === "ancestry" ? "ancestry" : "parent-plus-refs";
|
|
@@ -65,6 +65,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
65
65
|
const providerOptions = resolveProviderOptions(ctx, {
|
|
66
66
|
provider,
|
|
67
67
|
rawModel,
|
|
68
|
+
rawImageToolModel,
|
|
68
69
|
rawReasoningEffort,
|
|
69
70
|
rawSize: size,
|
|
70
71
|
rawWebSearchEnabled: body.webSearchEnabled,
|
|
@@ -80,6 +81,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
80
81
|
});
|
|
81
82
|
}
|
|
82
83
|
const imageModel = providerOptions.model;
|
|
84
|
+
const imageToolModel = providerOptions.imageToolModel;
|
|
83
85
|
const reasoningEffort = providerOptions.reasoningEffort;
|
|
84
86
|
const effectiveSize = providerOptions.size;
|
|
85
87
|
const webSearchEnabled = providerOptions.webSearchEnabled;
|
|
@@ -233,6 +235,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
233
235
|
clientNodeId,
|
|
234
236
|
quality,
|
|
235
237
|
model: effectiveImageModel,
|
|
238
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
236
239
|
size: effectiveSize,
|
|
237
240
|
moderation,
|
|
238
241
|
refs: refsForRequest.length,
|
|
@@ -267,7 +270,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
267
270
|
signal: cancelController.signal, prompt: generationPrompt, rawPrompt: prompt,
|
|
268
271
|
references: refCheck.refDetails, sourceImage: parentB64, contextMode, searchMode,
|
|
269
272
|
partialImages: emitProgress ? 2 : 0,
|
|
270
|
-
options: { model: effectiveImageModel, quality, size: effectiveSize, moderation,
|
|
273
|
+
options: { model: effectiveImageModel, imageToolModel, quality, size: effectiveSize, moderation,
|
|
271
274
|
mode: normalizedPromptMode, reasoningEffort, webSearchEnabled },
|
|
272
275
|
nai: activeProvider === "nai" ? readNaiOptions(req.body) : {},
|
|
273
276
|
}, emitProgress ? {
|
|
@@ -293,6 +296,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
293
296
|
parentNodeId,
|
|
294
297
|
clientNodeId,
|
|
295
298
|
model: effectiveImageModel,
|
|
299
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
296
300
|
moderation,
|
|
297
301
|
quality,
|
|
298
302
|
size: effectiveSize,
|
|
@@ -374,6 +378,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
374
378
|
promptMode: normalizedPromptMode,
|
|
375
379
|
options: { quality, size: effectiveSize, format: resultFormat, moderation },
|
|
376
380
|
model: effectiveImageModel,
|
|
381
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
377
382
|
reasoningEffort,
|
|
378
383
|
createdAt: Date.now(),
|
|
379
384
|
createdAtIso: new Date().toISOString(),
|
|
@@ -424,6 +429,7 @@ export async function runNodeGeneration(req, res, ctx) {
|
|
|
424
429
|
webSearchEnabled,
|
|
425
430
|
provider: activeProvider,
|
|
426
431
|
model: effectiveImageModel,
|
|
432
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
427
433
|
reasoningEffort,
|
|
428
434
|
size: effectiveSize,
|
|
429
435
|
format: resultFormat,
|
package/lib/oauthNormalize.js
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
// 0.09.12.2 — Keep supported image tool qualities intact for OAuth.
|
|
2
|
-
//
|
|
3
|
-
// the API response, UI metadata, and
|
|
2
|
+
// OAuth keeps low/medium/high; only explicitly selected API 2.5 tools add qualities.
|
|
3
|
+
// Keep the API response, UI metadata, and image_generation payload aligned.
|
|
4
4
|
export const DEFAULT_IMAGE_QUALITY = "medium";
|
|
5
5
|
export const VALID_IMAGE_QUALITIES = new Set(["low", "medium", "high"]);
|
|
6
|
+
export const API_IMAGE_TOOL_MODELS = ["gpt-image-2.5-sunburst", "gpt-image-2.5-flare"];
|
|
7
|
+
export const API_IMAGE_25_QUALITIES = new Set([...VALID_IMAGE_QUALITIES, "xhigh", "max"]);
|
|
8
|
+
export function isApiImageToolModel(value) {
|
|
9
|
+
return typeof value === "string" && API_IMAGE_TOOL_MODELS.some((model) => model === value);
|
|
10
|
+
}
|
|
11
|
+
export function normalizeImageToolModel(provider, value) {
|
|
12
|
+
if (provider !== "api" || value === undefined || value === null || value === "") {
|
|
13
|
+
return { imageToolModel: undefined };
|
|
14
|
+
}
|
|
15
|
+
if (isApiImageToolModel(value))
|
|
16
|
+
return { imageToolModel: value };
|
|
17
|
+
return {
|
|
18
|
+
error: `imageToolModel must be one of: ${API_IMAGE_TOOL_MODELS.join(", ")}`,
|
|
19
|
+
code: "INVALID_IMAGE_TOOL_MODEL",
|
|
20
|
+
status: 400,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
6
23
|
/**
|
|
7
24
|
* @param {{ provider?: string, quality?: string }} input
|
|
8
25
|
* @returns {{ quality: string, warnings: Array<{code:string,field:string,normalizedTo:string,reason:string}> }}
|
|
9
26
|
*/
|
|
10
27
|
export function normalizeOAuthParams(input) {
|
|
11
28
|
const requested = typeof input?.quality === "string" ? input.quality : DEFAULT_IMAGE_QUALITY;
|
|
12
|
-
|
|
29
|
+
const valid = input?.provider === "api" && isApiImageToolModel(input.imageToolModel)
|
|
30
|
+
? API_IMAGE_25_QUALITIES : VALID_IMAGE_QUALITIES;
|
|
31
|
+
if (valid.has(requested)) {
|
|
13
32
|
return { quality: requested, warnings: [] };
|
|
14
33
|
}
|
|
15
34
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const PROMPT_BUILDER_BACKENDS = ["auto", "oauth", "grok", "api", "grok-api"];
|
|
2
|
-
const GPT_MODELS = ["gpt-5.6-luna", "gpt-5.6-terra", "gpt-5.6-sol", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
|
|
2
|
+
const GPT_MODELS = ["gpt-5.6-luna", "gpt-6-astra", "gpt-5.6-terra", "gpt-5.6-sol", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
|
|
3
3
|
const grokModels = ["grok-4.3", "grok-4.6", "grok-4.5"];
|
|
4
4
|
export const PROMPT_BUILDER_MODELS = {
|
|
5
5
|
auto: ["auto"],
|
package/lib/providerOptions.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { normalizeImageToolModel } from "./oauthNormalize.js";
|
|
1
2
|
import { ATLASCLOUD_TEXT_TO_IMAGE_MODEL } from "./atlasCloudImageAdapter.js";
|
|
2
|
-
import { FALLBACK_IMAGE_MODEL, normalizeImageModel, normalizeReasoningEffort, normalizeGrokImageModel, normalizeGeminiApiModel, normalizeMinimaxImageModel, normalizeNaiImageModel, normalizeComfyWorkflowModel } from "./imageModels.js";
|
|
3
|
-
export function resolveProviderOptions(ctx, { provider = "oauth", rawModel, rawReasoningEffort, rawSize = "1024x1024", rawWebSearchEnabled = true, searchMode = "on", } = {}) {
|
|
3
|
+
import { FALLBACK_IMAGE_MODEL, coerceReasoningEffortForModel, normalizeImageModel, normalizeReasoningEffort, normalizeGrokImageModel, normalizeGeminiApiModel, normalizeMinimaxImageModel, normalizeNaiImageModel, normalizeComfyWorkflowModel } from "./imageModels.js";
|
|
4
|
+
export function resolveProviderOptions(ctx, { provider = "oauth", rawModel, rawImageToolModel, rawReasoningEffort, rawSize = "1024x1024", rawWebSearchEnabled = true, searchMode = "on", } = {}) {
|
|
4
5
|
if (provider === "agy") {
|
|
5
6
|
return {
|
|
6
7
|
provider: "agy",
|
|
@@ -117,6 +118,9 @@ export function resolveProviderOptions(ctx, { provider = "oauth", rawModel, rawR
|
|
|
117
118
|
};
|
|
118
119
|
}
|
|
119
120
|
const activeProvider = provider === "api" ? "api" : "oauth";
|
|
121
|
+
const toolModelCheck = normalizeImageToolModel(activeProvider, rawImageToolModel);
|
|
122
|
+
if (toolModelCheck.error)
|
|
123
|
+
return { error: toolModelCheck.error, code: toolModelCheck.code, status: toolModelCheck.status };
|
|
120
124
|
const apiConfig = ctx?.config?.apiProvider || {};
|
|
121
125
|
const modelInput = activeProvider === "api"
|
|
122
126
|
? (rawModel || apiConfig.defaultImageModel || FALLBACK_IMAGE_MODEL)
|
|
@@ -131,6 +135,9 @@ export function resolveProviderOptions(ctx, { provider = "oauth", rawModel, rawR
|
|
|
131
135
|
if (reasoningCheck.error) {
|
|
132
136
|
return { error: reasoningCheck.error, code: reasoningCheck.code, status: reasoningCheck.status };
|
|
133
137
|
}
|
|
138
|
+
// Applied after validation so an unsupported model/effort pairing cannot reach
|
|
139
|
+
// the upstream request. See coerceReasoningEffortForModel.
|
|
140
|
+
const effort = coerceReasoningEffortForModel(modelCheck.model, reasoningCheck.effort);
|
|
134
141
|
const size = activeProvider === "api" && (typeof rawSize !== "string" || rawSize.length === 0)
|
|
135
142
|
? (apiConfig.defaultSize || "1024x1024")
|
|
136
143
|
: rawSize;
|
|
@@ -139,8 +146,9 @@ export function resolveProviderOptions(ctx, { provider = "oauth", rawModel, rawR
|
|
|
139
146
|
: rawWebSearchEnabled !== false && searchMode !== "off";
|
|
140
147
|
return {
|
|
141
148
|
provider: activeProvider,
|
|
149
|
+
imageToolModel: toolModelCheck.imageToolModel,
|
|
142
150
|
model: modelCheck.model,
|
|
143
|
-
reasoningEffort:
|
|
151
|
+
reasoningEffort: effort,
|
|
144
152
|
size,
|
|
145
153
|
webSearchEnabled,
|
|
146
154
|
};
|
|
@@ -7,7 +7,7 @@ export function isOpenaiRequest(request) {
|
|
|
7
7
|
}
|
|
8
8
|
function prepareOpenaiClassic(ctx, request, _progress) {
|
|
9
9
|
const { provider: activeProvider, prompt: generationPrompt, requestId, background: backgroundParams } = request;
|
|
10
|
-
const { model: imageModel, quality, size: effectiveSize, moderation, mode: normalizedPromptMode, reasoningEffort, webSearchEnabled } = request.options;
|
|
10
|
+
const { model: imageModel, imageToolModel, quality, size: effectiveSize, moderation, mode: normalizedPromptMode, reasoningEffort, webSearchEnabled } = request.options;
|
|
11
11
|
// Scalars are captured at prepare; references, signal and ctx stay live per attempt.
|
|
12
12
|
const generateOne = async () => {
|
|
13
13
|
const MAX_RETRIES = 1;
|
|
@@ -15,7 +15,7 @@ function prepareOpenaiClassic(ctx, request, _progress) {
|
|
|
15
15
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
16
16
|
try {
|
|
17
17
|
const r = await generateViaResponses(activeProvider, generationPrompt, quality, effectiveSize, moderation, request.references, requestId, normalizedPromptMode, ctx, {
|
|
18
|
-
model: imageModel,
|
|
18
|
+
model: imageModel, imageToolModel,
|
|
19
19
|
reasoningEffort,
|
|
20
20
|
webSearchEnabled,
|
|
21
21
|
signal: request.signal,
|
|
@@ -50,21 +50,21 @@ function prepareOpenaiClassic(ctx, request, _progress) {
|
|
|
50
50
|
}
|
|
51
51
|
async function executeOpenaiNode(ctx, request, progress) {
|
|
52
52
|
const { provider, sourceImage: parentB64, prompt: generationPrompt, references, requestId, signal, searchMode, options } = request;
|
|
53
|
-
const { model, size, quality, moderation, mode, reasoningEffort, webSearchEnabled } = options;
|
|
53
|
+
const { model, imageToolModel, size, quality, moderation, mode, reasoningEffort, webSearchEnabled } = options;
|
|
54
54
|
const refsForRequest = request.contextMode === "parent-only" ? [] : references;
|
|
55
55
|
return parentB64
|
|
56
56
|
? await editViaResponses(provider, generationPrompt, parentB64, quality, size, moderation, mode, ctx, requestId, {
|
|
57
|
-
model, references: refsForRequest, searchMode, reasoningEffort, webSearchEnabled, signal,
|
|
57
|
+
model, imageToolModel, references: refsForRequest, searchMode, reasoningEffort, webSearchEnabled, signal,
|
|
58
58
|
})
|
|
59
59
|
: await generateViaResponses(provider, generationPrompt, quality, size, moderation, refsForRequest, requestId, mode, ctx, {
|
|
60
|
-
model, reasoningEffort, webSearchEnabled, signal,
|
|
60
|
+
model, imageToolModel, reasoningEffort, webSearchEnabled, signal,
|
|
61
61
|
partialImages: request.partialImages,
|
|
62
62
|
onPartialImage: progress?.onPartialImage ?? null,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
async function executeOpenaiEdit(ctx, request) {
|
|
66
66
|
const { provider, rawPrompt, sourceImage, signal, requestId, options } = request;
|
|
67
|
-
const result = await editViaResponses(provider, rawPrompt, sourceImage, options.quality, options.size, options.moderation, options.mode, ctx, requestId, { model: options.model, reasoningEffort: options.reasoningEffort,
|
|
67
|
+
const result = await editViaResponses(provider, rawPrompt, sourceImage, options.quality, options.size, options.moderation, options.mode, ctx, requestId, { model: options.model, imageToolModel: options.imageToolModel, reasoningEffort: options.reasoningEffort,
|
|
68
68
|
webSearchEnabled: options.webSearchEnabled,
|
|
69
69
|
...(request.mask !== null ? { mask: request.mask } : {}), signal });
|
|
70
70
|
// Preserve native retry metadata; only Responses had these caller defaults.
|
|
@@ -72,7 +72,7 @@ async function executeOpenaiEdit(ctx, request) {
|
|
|
72
72
|
}
|
|
73
73
|
async function executeOpenaiMultimode(ctx, request, progress) {
|
|
74
74
|
const { provider, prompt, references, signal, requestId, options, maxImages } = request;
|
|
75
|
-
return generateMultimodeViaResponses(provider, prompt, options.quality, options.size, options.moderation, references, requestId, options.mode, ctx, { model: options.model, maxImages, reasoningEffort: options.reasoningEffort,
|
|
75
|
+
return generateMultimodeViaResponses(provider, prompt, options.quality, options.size, options.moderation, references, requestId, options.mode, ctx, { model: options.model, imageToolModel: options.imageToolModel, maxImages, reasoningEffort: options.reasoningEffort,
|
|
76
76
|
webSearchEnabled: options.webSearchEnabled,
|
|
77
77
|
...(progress.onPartialImage !== undefined ? { onPartialImage: progress.onPartialImage } : {}),
|
|
78
78
|
...(progress.onFinalImage !== undefined ? { onFinalImage: progress.onFinalImage } : {}), signal });
|
|
@@ -5,6 +5,7 @@ import { imageToolChoice, imageToolChoiceKind, tools, toolTypes, } from "../../r
|
|
|
5
5
|
import { emptyResponseError } from "../../responsesErrors.js";
|
|
6
6
|
import { retryPromptOnlyJsonImage } from "../../responsesFallback.js";
|
|
7
7
|
import { AUTO_PROMPT_FIDELITY_SUFFIX, DIRECT_PROMPT_FIDELITY_SUFFIX, EDIT_DEVELOPER_PROMPT, EDIT_NO_SEARCH_DEVELOPER_PROMPT, GENERATE_DEVELOPER_PROMPT, GENERATE_NO_SEARCH_DEVELOPER_PROMPT, MULTIMODE_DEVELOPER_PROMPT, MULTIMODE_NO_SEARCH_DEVELOPER_PROMPT, buildEditTextPrompt, buildMultimodeSequencePrompt, buildUserTextPrompt, } from "../../oauthProxy.js";
|
|
8
|
+
import { normalizeOAuthParams, normalizeImageToolModel } from "../../oauthNormalize.js";
|
|
8
9
|
import { postResponses } from "../../responsesTransport.js";
|
|
9
10
|
function normalizeRef(ref) {
|
|
10
11
|
const b64 = typeof ref === "string" ? ref : ref?.b64;
|
|
@@ -23,7 +24,13 @@ export async function generateViaResponses(provider, prompt, quality, size, mode
|
|
|
23
24
|
const ctx = requireRuntimeContext(ctxRaw);
|
|
24
25
|
const model = options.model || ctx.config?.imageModels?.default || "gpt-5.6-luna";
|
|
25
26
|
const webSearchEnabled = options.webSearchEnabled !== false && options.searchMode !== "off";
|
|
26
|
-
const
|
|
27
|
+
const toolModel = normalizeImageToolModel(provider ?? "oauth", options.imageToolModel);
|
|
28
|
+
if (toolModel.error)
|
|
29
|
+
throw Object.assign(new Error(toolModel.error), { code: toolModel.code, status: toolModel.status });
|
|
30
|
+
if (quality === "xhigh" || quality === "max") {
|
|
31
|
+
quality = normalizeOAuthParams({ provider, quality, imageToolModel: toolModel.imageToolModel }).quality;
|
|
32
|
+
}
|
|
33
|
+
const requestTools = tools(webSearchEnabled, { ...(toolModel.imageToolModel ? { model: toolModel.imageToolModel } : {}),
|
|
27
34
|
quality,
|
|
28
35
|
size,
|
|
29
36
|
moderation,
|
|
@@ -105,7 +112,13 @@ export async function generateMultimodeViaResponses(provider, prompt, quality, s
|
|
|
105
112
|
const maxImages = Math.min(maxGeneratedImages, Math.max(1, Math.trunc(Number(options.maxImages) || 1)));
|
|
106
113
|
const model = options.model || ctx.config?.imageModels?.default || "gpt-5.6-luna";
|
|
107
114
|
const webSearchEnabled = options.webSearchEnabled !== false && options.searchMode !== "off";
|
|
108
|
-
const
|
|
115
|
+
const toolModel = normalizeImageToolModel(provider ?? "oauth", options.imageToolModel);
|
|
116
|
+
if (toolModel.error)
|
|
117
|
+
throw Object.assign(new Error(toolModel.error), { code: toolModel.code, status: toolModel.status });
|
|
118
|
+
if (quality === "xhigh" || quality === "max") {
|
|
119
|
+
quality = normalizeOAuthParams({ provider, quality, imageToolModel: toolModel.imageToolModel }).quality;
|
|
120
|
+
}
|
|
121
|
+
const requestTools = tools(webSearchEnabled, { ...(toolModel.imageToolModel ? { model: toolModel.imageToolModel } : {}), quality, size, moderation, ...(options.partialImages ? { partial_images: options.partialImages } : {}) });
|
|
109
122
|
const userText = buildMultimodeSequencePrompt(mode === "direct"
|
|
110
123
|
? `${prompt}${DIRECT_PROMPT_FIDELITY_SUFFIX}`
|
|
111
124
|
: `${prompt}${webSearchEnabled ? "" : ""}${AUTO_PROMPT_FIDELITY_SUFFIX}`, maxImages, { webSearchEnabled, size });
|
|
@@ -139,7 +152,13 @@ export async function editViaResponses(provider, prompt, imageB64, quality, size
|
|
|
139
152
|
const ctx = requireRuntimeContext(ctxRaw);
|
|
140
153
|
const model = options.model || ctx.config?.imageModels?.default || "gpt-5.6-luna";
|
|
141
154
|
const webSearchEnabled = options.webSearchEnabled !== false && options.searchMode !== "off";
|
|
142
|
-
const
|
|
155
|
+
const toolModel = normalizeImageToolModel(provider ?? "oauth", options.imageToolModel);
|
|
156
|
+
if (toolModel.error)
|
|
157
|
+
throw Object.assign(new Error(toolModel.error), { code: toolModel.code, status: toolModel.status });
|
|
158
|
+
if (quality === "xhigh" || quality === "max") {
|
|
159
|
+
quality = normalizeOAuthParams({ provider, quality, imageToolModel: toolModel.imageToolModel }).quality;
|
|
160
|
+
}
|
|
161
|
+
const requestTools = tools(webSearchEnabled, { ...(toolModel.imageToolModel ? { model: toolModel.imageToolModel } : {}), quality, size, moderation });
|
|
143
162
|
const toolChoice = imageToolChoice(options.forceImageToolChoice ?? ctx.config?.oauth?.forceImageToolChoice !== false);
|
|
144
163
|
const toolChoiceKind = imageToolChoiceKind(toolChoice);
|
|
145
164
|
const imageForRequest = await compressReferenceB64ForOAuth(imageB64, {
|
|
@@ -26,6 +26,7 @@ export const REGISTRY = [
|
|
|
26
26
|
{ id: "gpt-5.6-sol", aliases: ["sol"], kind: "image", supports: RESPONSES },
|
|
27
27
|
{ id: "gpt-5.6-terra", aliases: ["terra"], kind: "image", supports: RESPONSES },
|
|
28
28
|
{ id: "gpt-5.6-luna", aliases: ["luna"], kind: "image", supports: RESPONSES },
|
|
29
|
+
{ id: "gpt-6-astra", aliases: ["astra"], kind: "image", supports: RESPONSES },
|
|
29
30
|
{ id: "gpt-5.3-codex-spark", aliases: ["spark"], kind: "image", supports: UNSUPPORTED },
|
|
30
31
|
],
|
|
31
32
|
referenceLimits: {},
|
|
@@ -52,6 +53,7 @@ export const REGISTRY = [
|
|
|
52
53
|
{ id: "gpt-5.6-sol", aliases: ["sol"], kind: "image", supports: RESPONSES },
|
|
53
54
|
{ id: "gpt-5.6-terra", aliases: ["terra"], kind: "image", supports: RESPONSES },
|
|
54
55
|
{ id: "gpt-5.6-luna", aliases: ["luna"], kind: "image", supports: RESPONSES },
|
|
56
|
+
{ id: "gpt-6-astra", aliases: ["astra"], kind: "image", supports: RESPONSES },
|
|
55
57
|
],
|
|
56
58
|
referenceLimits: {},
|
|
57
59
|
elementTaxonomy: "gpt",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ima2-gen",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"packageManager": "npm@11.18.0",
|
|
5
5
|
"description": "Local-first visual generation runtime and studio for people and coding agents, with reproducible image and video workflows across multiple providers.",
|
|
6
6
|
"type": "module",
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
"@openai/codex": "0.153.4",
|
|
96
96
|
"better-sqlite3": "^13.0.3",
|
|
97
97
|
"dotenv": "^17.4.2",
|
|
98
|
+
"electron-updater": "6.8.9",
|
|
98
99
|
"express": "^5.1.0",
|
|
99
100
|
"google-auth-library": "^11.0.1",
|
|
100
101
|
"openai": "^7.4.0",
|
|
@@ -125,5 +126,5 @@
|
|
|
125
126
|
"typescript": "^5.9.3",
|
|
126
127
|
"yaml": "2.9.0"
|
|
127
128
|
},
|
|
128
|
-
"gitHead": "
|
|
129
|
+
"gitHead": "bfb83da57b1497e9581cf51bfd7213272d79c9e2"
|
|
129
130
|
}
|
package/routes/edit.js
CHANGED
|
@@ -90,11 +90,12 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
90
90
|
let jobOwned = false;
|
|
91
91
|
const cancelController = new AbortController();
|
|
92
92
|
try {
|
|
93
|
-
const { prompt, image: imageB64, mask: rawMask, quality: rawQuality = "medium", size = "1024x1024", moderation = "low", provider = "oauth", mode: promptMode = "auto", model: rawModel, reasoningEffort: rawReasoningEffort, webSearchEnabled: rawWebSearchEnabled = true, } = req.body;
|
|
94
|
-
const { quality, warnings: qualityWarnings } = normalizeOAuthParams({ provider, quality: rawQuality });
|
|
93
|
+
const { prompt, image: imageB64, mask: rawMask, quality: rawQuality = "medium", size = "1024x1024", moderation = "low", provider = "oauth", mode: promptMode = "auto", model: rawModel, imageToolModel: rawImageToolModel, reasoningEffort: rawReasoningEffort, webSearchEnabled: rawWebSearchEnabled = true, } = req.body;
|
|
94
|
+
const { quality, warnings: qualityWarnings } = normalizeOAuthParams({ provider, quality: rawQuality, imageToolModel: rawImageToolModel });
|
|
95
95
|
const providerOptions = resolveProviderOptions(ctx, {
|
|
96
96
|
provider,
|
|
97
97
|
rawModel,
|
|
98
|
+
rawImageToolModel,
|
|
98
99
|
rawReasoningEffort,
|
|
99
100
|
rawSize: size,
|
|
100
101
|
rawWebSearchEnabled,
|
|
@@ -106,6 +107,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
106
107
|
return res.status(providerOptions.status).json({ error: providerOptions.error, code: providerOptions.code });
|
|
107
108
|
}
|
|
108
109
|
const imageModel = providerOptions.model;
|
|
110
|
+
const imageToolModel = providerOptions.imageToolModel;
|
|
109
111
|
const reasoningEffort = providerOptions.reasoningEffort;
|
|
110
112
|
const effectiveSize = providerOptions.size;
|
|
111
113
|
const webSearchEnabled = providerOptions.webSearchEnabled;
|
|
@@ -133,6 +135,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
133
135
|
sessionId,
|
|
134
136
|
quality,
|
|
135
137
|
model: imageModel,
|
|
138
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
136
139
|
size: effectiveSize,
|
|
137
140
|
},
|
|
138
141
|
});
|
|
@@ -203,6 +206,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
203
206
|
provider: activeProvider,
|
|
204
207
|
quality,
|
|
205
208
|
model: imageModel,
|
|
209
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
206
210
|
size: effectiveSize,
|
|
207
211
|
moderation,
|
|
208
212
|
sessionId,
|
|
@@ -218,7 +222,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
218
222
|
surface: "edit", provider: activeProvider, requestId,
|
|
219
223
|
signal: cancelController.signal, prompt, rawPrompt: prompt,
|
|
220
224
|
sourceImage: imageB64, mask: maskCheck.mask ?? null, references: [],
|
|
221
|
-
options: { model: imageModel, quality, size: effectiveSize, moderation,
|
|
225
|
+
options: { model: imageModel, imageToolModel, quality, size: effectiveSize, moderation,
|
|
222
226
|
mode: normalizedPromptMode, reasoningEffort, webSearchEnabled },
|
|
223
227
|
})).execute();
|
|
224
228
|
const resultB64 = r.b64;
|
|
@@ -270,6 +274,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
270
274
|
size: effectiveSize,
|
|
271
275
|
moderation,
|
|
272
276
|
model: imageModel,
|
|
277
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
273
278
|
reasoningEffort,
|
|
274
279
|
elapsed,
|
|
275
280
|
format: editExt,
|
|
@@ -304,6 +309,7 @@ export function registerEditRoutes(app, ctxRaw) {
|
|
|
304
309
|
usage,
|
|
305
310
|
provider: activeProvider,
|
|
306
311
|
model: activeProvider === "grok" ? resolveGrokQualityModel(imageModel, quality) : imageModel,
|
|
312
|
+
...(imageToolModel ? { imageToolModel } : {}),
|
|
307
313
|
moderation,
|
|
308
314
|
warnings: qualityWarnings,
|
|
309
315
|
revisedPrompt: revisedPrompt || null,
|