ima2-gen 1.1.7 → 1.1.9

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.
Files changed (229) hide show
  1. package/README.md +56 -27
  2. package/bin/commands/annotate.js +137 -0
  3. package/bin/commands/annotate.ts +118 -0
  4. package/bin/commands/cancel.js +37 -33
  5. package/bin/commands/cancel.ts +45 -0
  6. package/bin/commands/canvas-versions.js +91 -0
  7. package/bin/commands/canvas-versions.ts +80 -0
  8. package/bin/commands/cardnews.js +293 -0
  9. package/bin/commands/cardnews.ts +248 -0
  10. package/bin/commands/comfy.js +63 -0
  11. package/bin/commands/comfy.ts +54 -0
  12. package/bin/commands/config.js +270 -0
  13. package/bin/commands/config.ts +265 -0
  14. package/bin/commands/edit.js +97 -72
  15. package/bin/commands/edit.ts +116 -0
  16. package/bin/commands/gen.js +140 -118
  17. package/bin/commands/gen.ts +176 -0
  18. package/bin/commands/history.js +164 -0
  19. package/bin/commands/history.ts +145 -0
  20. package/bin/commands/ls.js +60 -42
  21. package/bin/commands/ls.ts +60 -0
  22. package/bin/commands/metadata.js +45 -0
  23. package/bin/commands/metadata.ts +36 -0
  24. package/bin/commands/multimode.js +159 -0
  25. package/bin/commands/multimode.ts +146 -0
  26. package/bin/commands/node.js +176 -0
  27. package/bin/commands/node.ts +157 -0
  28. package/bin/commands/observability.js +201 -0
  29. package/bin/commands/observability.ts +176 -0
  30. package/bin/commands/ping.js +26 -20
  31. package/bin/commands/ping.ts +29 -0
  32. package/bin/commands/prompt.js +506 -0
  33. package/bin/commands/prompt.ts +421 -0
  34. package/bin/commands/ps.js +78 -71
  35. package/bin/commands/ps.ts +78 -0
  36. package/bin/commands/session.js +308 -0
  37. package/bin/commands/session.ts +265 -0
  38. package/bin/commands/show.js +75 -40
  39. package/bin/commands/show.ts +69 -0
  40. package/bin/ima2.js +324 -310
  41. package/bin/ima2.ts +444 -0
  42. package/bin/lib/args.js +75 -66
  43. package/bin/lib/args.ts +73 -0
  44. package/bin/lib/browser-id.js +15 -0
  45. package/bin/lib/browser-id.ts +16 -0
  46. package/bin/lib/client.js +91 -83
  47. package/bin/lib/client.ts +109 -0
  48. package/bin/lib/error-hints.js +14 -17
  49. package/bin/lib/error-hints.ts +23 -0
  50. package/bin/lib/files.js +26 -28
  51. package/bin/lib/files.ts +39 -0
  52. package/bin/lib/output.js +44 -42
  53. package/bin/lib/output.ts +58 -0
  54. package/bin/lib/platform.js +60 -56
  55. package/bin/lib/platform.ts +97 -0
  56. package/bin/lib/sse.js +73 -0
  57. package/bin/lib/sse.ts +73 -0
  58. package/bin/lib/star-prompt.js +69 -76
  59. package/bin/lib/star-prompt.ts +97 -0
  60. package/bin/lib/storage-doctor.js +34 -35
  61. package/bin/lib/storage-doctor.ts +38 -0
  62. package/config.js +147 -190
  63. package/config.ts +331 -0
  64. package/docs/API.md +48 -8
  65. package/docs/CLI.md +190 -0
  66. package/docs/FAQ.ko.md +5 -5
  67. package/docs/FAQ.md +5 -5
  68. package/docs/README.ja.md +71 -25
  69. package/docs/README.ko.md +61 -24
  70. package/docs/README.zh-CN.md +73 -27
  71. package/lib/assetLifecycle.js +130 -130
  72. package/lib/assetLifecycle.ts +142 -0
  73. package/lib/canvasVersionStore.js +135 -153
  74. package/lib/canvasVersionStore.ts +181 -0
  75. package/lib/cardNewsGenerator.js +127 -142
  76. package/lib/cardNewsGenerator.ts +162 -0
  77. package/lib/cardNewsJobStore.js +78 -84
  78. package/lib/cardNewsJobStore.ts +107 -0
  79. package/lib/cardNewsManifestStore.js +88 -93
  80. package/lib/cardNewsManifestStore.ts +112 -0
  81. package/lib/cardNewsPlanner.js +157 -152
  82. package/lib/cardNewsPlanner.ts +180 -0
  83. package/lib/cardNewsPlannerClient.js +101 -98
  84. package/lib/cardNewsPlannerClient.ts +114 -0
  85. package/lib/cardNewsPlannerPrompt.js +56 -56
  86. package/lib/cardNewsPlannerPrompt.ts +60 -0
  87. package/lib/cardNewsPlannerSchema.js +231 -223
  88. package/lib/cardNewsPlannerSchema.ts +259 -0
  89. package/lib/cardNewsRoleTemplateStore.js +39 -41
  90. package/lib/cardNewsRoleTemplateStore.ts +47 -0
  91. package/lib/cardNewsTemplateStore.js +171 -175
  92. package/lib/cardNewsTemplateStore.ts +210 -0
  93. package/lib/codexDetect.js +44 -47
  94. package/lib/codexDetect.ts +69 -0
  95. package/lib/comfyBridge.js +164 -184
  96. package/lib/comfyBridge.ts +214 -0
  97. package/lib/db.js +41 -51
  98. package/lib/db.ts +166 -0
  99. package/lib/errorClassify.js +62 -78
  100. package/lib/errorClassify.ts +100 -0
  101. package/lib/generationErrors.js +140 -103
  102. package/lib/generationErrors.ts +125 -0
  103. package/lib/historyList.js +149 -147
  104. package/lib/historyList.ts +164 -0
  105. package/lib/imageMetadata.js +86 -89
  106. package/lib/imageMetadata.ts +111 -0
  107. package/lib/imageMetadataStore.js +46 -51
  108. package/lib/imageMetadataStore.ts +67 -0
  109. package/lib/imageModels.js +38 -45
  110. package/lib/imageModels.ts +52 -0
  111. package/lib/inflight.js +131 -150
  112. package/lib/inflight.ts +204 -0
  113. package/lib/localImportStore.js +105 -0
  114. package/lib/localImportStore.ts +111 -0
  115. package/lib/logger.js +105 -112
  116. package/lib/logger.ts +150 -0
  117. package/lib/nodeStore.js +65 -64
  118. package/lib/nodeStore.ts +81 -0
  119. package/lib/oauthLauncher.js +61 -59
  120. package/lib/oauthLauncher.ts +64 -0
  121. package/lib/oauthNormalize.js +15 -19
  122. package/lib/oauthNormalize.ts +30 -0
  123. package/lib/oauthProxy.js +834 -832
  124. package/lib/oauthProxy.ts +995 -0
  125. package/lib/openDirectory.js +41 -40
  126. package/lib/openDirectory.ts +45 -0
  127. package/lib/pngInfo.js +18 -20
  128. package/lib/pngInfo.ts +26 -0
  129. package/lib/promptImport/curatedSources.js +135 -0
  130. package/lib/promptImport/curatedSources.ts +139 -0
  131. package/lib/promptImport/discoveryRegistry.js +218 -0
  132. package/lib/promptImport/discoveryRegistry.ts +236 -0
  133. package/lib/promptImport/errors.js +10 -10
  134. package/lib/promptImport/errors.ts +18 -0
  135. package/lib/promptImport/githubDiscovery.js +238 -0
  136. package/lib/promptImport/githubDiscovery.ts +248 -0
  137. package/lib/promptImport/githubFolder.js +302 -0
  138. package/lib/promptImport/githubFolder.ts +308 -0
  139. package/lib/promptImport/githubSource.js +194 -171
  140. package/lib/promptImport/githubSource.ts +239 -0
  141. package/lib/promptImport/gptImageHints.js +61 -0
  142. package/lib/promptImport/gptImageHints.ts +68 -0
  143. package/lib/promptImport/parsePromptCandidates.js +110 -112
  144. package/lib/promptImport/parsePromptCandidates.ts +153 -0
  145. package/lib/promptImport/promptIndex.js +230 -0
  146. package/lib/promptImport/promptIndex.ts +248 -0
  147. package/lib/promptImport/rankPromptCandidates.js +52 -0
  148. package/lib/promptImport/rankPromptCandidates.ts +49 -0
  149. package/lib/providerOptions.js +31 -0
  150. package/lib/providerOptions.ts +41 -0
  151. package/lib/referenceImageCompress.js +51 -62
  152. package/lib/referenceImageCompress.ts +75 -0
  153. package/lib/refs.js +93 -81
  154. package/lib/refs.ts +117 -0
  155. package/lib/requestLogger.js +32 -38
  156. package/lib/requestLogger.ts +48 -0
  157. package/lib/responsesImageAdapter.js +351 -0
  158. package/lib/responsesImageAdapter.ts +352 -0
  159. package/lib/runtimePorts.js +71 -73
  160. package/lib/runtimePorts.ts +93 -0
  161. package/lib/sessionStore.js +179 -230
  162. package/lib/sessionStore.ts +272 -0
  163. package/lib/storageMigration.js +247 -245
  164. package/lib/storageMigration.ts +284 -0
  165. package/lib/styleSheet.js +86 -90
  166. package/lib/styleSheet.ts +128 -0
  167. package/lib/systemTrash.js +18 -0
  168. package/lib/systemTrash.ts +20 -0
  169. package/package.json +26 -10
  170. package/routes/annotations.js +76 -79
  171. package/routes/annotations.ts +95 -0
  172. package/routes/canvasVersions.js +50 -54
  173. package/routes/canvasVersions.ts +64 -0
  174. package/routes/cardNews.js +158 -171
  175. package/routes/cardNews.ts +183 -0
  176. package/routes/comfy.js +23 -31
  177. package/routes/comfy.ts +39 -0
  178. package/routes/edit.js +183 -214
  179. package/routes/edit.ts +230 -0
  180. package/routes/generate.js +269 -291
  181. package/routes/generate.ts +309 -0
  182. package/routes/health.js +102 -107
  183. package/routes/health.ts +114 -0
  184. package/routes/history.js +136 -144
  185. package/routes/history.ts +153 -0
  186. package/routes/imageImport.js +33 -0
  187. package/routes/imageImport.ts +33 -0
  188. package/routes/index.js +18 -16
  189. package/routes/index.ts +35 -0
  190. package/routes/metadata.js +60 -64
  191. package/routes/metadata.ts +71 -0
  192. package/routes/multimode.js +228 -263
  193. package/routes/multimode.ts +280 -0
  194. package/routes/nodes.js +378 -424
  195. package/routes/nodes.ts +455 -0
  196. package/routes/promptImport.js +291 -152
  197. package/routes/promptImport.ts +354 -0
  198. package/routes/prompts.js +333 -360
  199. package/routes/prompts.ts +379 -0
  200. package/routes/sessions.js +277 -285
  201. package/routes/sessions.ts +292 -0
  202. package/routes/storage.js +29 -31
  203. package/routes/storage.ts +39 -0
  204. package/server.js +189 -196
  205. package/server.ts +235 -0
  206. package/ui/dist/.vite/manifest.json +101 -0
  207. package/ui/dist/assets/CardNewsWorkspace-BJOCey7Z.js +2 -0
  208. package/ui/dist/assets/NodeCanvas-BZV40eAE.css +1 -0
  209. package/ui/dist/assets/NodeCanvas-C3dzYNsk.js +7 -0
  210. package/ui/dist/assets/PromptImportDialog-Dqu1VpUh.js +2 -0
  211. package/ui/dist/assets/PromptImportDiscoverySection-Dg8T9X0L.js +1 -0
  212. package/ui/dist/assets/PromptImportFolderSection-DBaqsFO4.js +1 -0
  213. package/ui/dist/assets/PromptLibraryPanel-p5QqR97M.js +2 -0
  214. package/ui/dist/assets/SettingsWorkspace-B5bSAZ6u.js +1 -0
  215. package/ui/dist/assets/index-C9cXwiWE.js +25 -0
  216. package/ui/dist/assets/index-CGMIkZXn.css +1 -0
  217. package/ui/dist/assets/index-Cvld7dUZ.js +1 -0
  218. package/ui/dist/index.html +6 -3
  219. package/assets/screenshot.png +0 -0
  220. package/assets/screenshots/classic-generate-light.png +0 -0
  221. package/assets/screenshots/node-graph-branching.png +0 -0
  222. package/assets/screenshots/settings-oauth-generation.png +0 -0
  223. package/assets/screenshots/settings-workspace.png +0 -0
  224. package/assets/screenshots/style-sheet-editor.png +0 -0
  225. package/integrations/comfyui/ima2_gen_bridge/__pycache__/__init__.cpython-313.pyc +0 -0
  226. package/integrations/comfyui/ima2_gen_bridge/__pycache__/nodes.cpython-313.pyc +0 -0
  227. package/ui/dist/assets/index-DARPdT4Q.css +0 -1
  228. package/ui/dist/assets/index-ht80GMq4.js +0 -31
  229. package/ui/dist/assets/index-ht80GMq4.js.map +0 -1
@@ -0,0 +1,280 @@
1
+ import { mkdir, writeFile } from "fs/promises";
2
+ import { join } from "path";
3
+ import { randomBytes } from "crypto";
4
+ import { summarizeReferencePayload, validateAndNormalizeRefs } from "../lib/refs.js";
5
+ import { classifyUpstreamError } from "../lib/errorClassify.js";
6
+ import { normalizeOAuthParams } from "../lib/oauthNormalize.js";
7
+ import { resolveProviderOptions } from "../lib/providerOptions.js";
8
+ import { generateMultimodeViaResponses } from "../lib/responsesImageAdapter.js";
9
+ import { startJob, finishJob } from "../lib/inflight.js";
10
+ import { logEvent, logError } from "../lib/logger.js";
11
+ import { embedImageMetadataBestEffort } from "../lib/imageMetadataStore.js";
12
+
13
+ function sendSse(res, event, data) {
14
+ res.write(`event: ${event}\n`);
15
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
16
+ }
17
+
18
+ function validateModeration(ctx, moderation) {
19
+ if (typeof moderation !== "string" || !ctx.config.oauth.validModeration.has(moderation)) {
20
+ return { error: "moderation must be one of: auto, low" };
21
+ }
22
+ return { moderation };
23
+ }
24
+
25
+ function normalizeMaxImages(value) {
26
+ return Math.min(8, Math.max(1, Math.trunc(Number(value) || 1)));
27
+ }
28
+
29
+ function sequenceStatus(returned, requested) {
30
+ if (returned <= 0) return "empty";
31
+ if (returned < requested) return "partial";
32
+ return "complete";
33
+ }
34
+
35
+ export function registerMultimodeRoutes(app, ctx) {
36
+ app.post("/api/generate/multimode", async (req, res) => {
37
+ const requestId = typeof req.body?.requestId === "string" ? req.body.requestId : req.id;
38
+ let finishStatus = "completed";
39
+ let finishHttpStatus = 200;
40
+ let finishErrorCode;
41
+ let finishMeta = {};
42
+
43
+ res.setHeader("Content-Type", "text/event-stream; charset=utf-8");
44
+ res.setHeader("Cache-Control", "no-cache, no-transform");
45
+ res.setHeader("Connection", "keep-alive");
46
+ res.flushHeaders?.();
47
+
48
+ try {
49
+ const {
50
+ prompt,
51
+ quality: rawQuality = "medium",
52
+ size = "1024x1024",
53
+ format = "png",
54
+ moderation = "low",
55
+ provider = "auto",
56
+ references = [],
57
+ mode: promptMode = "auto",
58
+ model: rawModel,
59
+ reasoningEffort: rawReasoningEffort,
60
+ webSearchEnabled: rawWebSearchEnabled = true,
61
+ } = req.body;
62
+ const maxImages = normalizeMaxImages(req.body?.maxImages);
63
+ const normalizedPromptMode = promptMode === "direct" ? "direct" : "auto";
64
+ const { quality, warnings: qualityWarnings } = normalizeOAuthParams({ provider, quality: rawQuality });
65
+ const providerOptions = resolveProviderOptions(ctx, {
66
+ provider,
67
+ rawModel,
68
+ rawReasoningEffort,
69
+ rawSize: size,
70
+ rawWebSearchEnabled,
71
+ });
72
+ if (providerOptions.error) {
73
+ finishStatus = "error";
74
+ finishHttpStatus = providerOptions.status;
75
+ finishErrorCode = providerOptions.code;
76
+ sendSse(res, "error", { error: providerOptions.error, code: providerOptions.code, status: providerOptions.status, requestId });
77
+ return;
78
+ }
79
+ const imageModel = providerOptions.model;
80
+ const reasoningEffort = providerOptions.reasoningEffort;
81
+ const effectiveSize = providerOptions.size;
82
+ const webSearchEnabled = providerOptions.webSearchEnabled;
83
+ const activeProvider = providerOptions.provider;
84
+ if (!prompt) {
85
+ finishStatus = "error";
86
+ finishHttpStatus = 400;
87
+ finishErrorCode = "PROMPT_REQUIRED";
88
+ sendSse(res, "error", { error: "Prompt is required", code: finishErrorCode, status: 400, requestId });
89
+ return;
90
+ }
91
+ const moderationCheck = validateModeration(ctx, moderation);
92
+ if (moderationCheck.error) {
93
+ finishStatus = "error";
94
+ finishHttpStatus = 400;
95
+ finishErrorCode = "INVALID_MODERATION";
96
+ sendSse(res, "error", { error: moderationCheck.error, code: finishErrorCode, status: 400, requestId });
97
+ return;
98
+ }
99
+ const refCheck = validateAndNormalizeRefs(references);
100
+ if (refCheck.error) {
101
+ finishStatus = "error";
102
+ finishHttpStatus = 400;
103
+ finishErrorCode = refCheck.code;
104
+ sendSse(res, "error", { error: refCheck.error, code: refCheck.code, status: 400, requestId });
105
+ return;
106
+ }
107
+ const referencePayload = summarizeReferencePayload(references);
108
+
109
+ startJob({
110
+ requestId,
111
+ kind: "multimode",
112
+ prompt,
113
+ meta: {
114
+ kind: "multimode",
115
+ quality,
116
+ model: imageModel,
117
+ size: effectiveSize,
118
+ maxImages,
119
+ refsCount: referencePayload.refsCount,
120
+ referenceBytes: referencePayload.referenceBytes,
121
+ referenceB64Chars: referencePayload.referenceB64Chars,
122
+ },
123
+ });
124
+
125
+ logEvent("multimode", "request", {
126
+ requestId,
127
+ quality,
128
+ model: imageModel,
129
+ size: effectiveSize,
130
+ moderation,
131
+ maxImages,
132
+ refs: refCheck.refs.length,
133
+ referenceBytes: referencePayload.referenceBytes,
134
+ promptChars: typeof prompt === "string" ? prompt.length : 0,
135
+ webSearchEnabled,
136
+ });
137
+
138
+ const startTime = Date.now();
139
+ const mimeMap = { png: "image/png", jpeg: "image/jpeg", webp: "image/webp" };
140
+ const mime = mimeMap[format] || "image/png";
141
+ const sequenceId = `seq_${Date.now().toString(36)}_${randomBytes(4).toString("hex")}`;
142
+ await mkdir(ctx.config.storage.generatedDir, { recursive: true });
143
+
144
+ sendSse(res, "phase", { phase: "streaming", requestId, sequenceId, maxImages });
145
+ const generated = await generateMultimodeViaResponses(
146
+ activeProvider,
147
+ prompt,
148
+ quality,
149
+ effectiveSize,
150
+ moderation,
151
+ refCheck.refDetails || refCheck.refs,
152
+ requestId,
153
+ normalizedPromptMode,
154
+ ctx,
155
+ {
156
+ model: imageModel,
157
+ maxImages,
158
+ reasoningEffort,
159
+ webSearchEnabled,
160
+ onPartialImage: (partial) =>
161
+ sendSse(res, "partial", {
162
+ image: `data:${mime};base64,${partial.b64}`,
163
+ requestId,
164
+ sequenceId,
165
+ index: partial.index,
166
+ }),
167
+ },
168
+ );
169
+
170
+ const returned = generated.images.length;
171
+ const status = sequenceStatus(returned, maxImages);
172
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
173
+ const images = [];
174
+
175
+ for (const [index, image] of generated.images.entries()) {
176
+ const rand = randomBytes(ctx.config.ids.generatedHexBytes).toString("hex");
177
+ const filename = `${Date.now()}_${rand}_multimode_${index}.${format}`;
178
+ const meta = {
179
+ kind: "multimode-image",
180
+ generationStrategy: "one-call-text-sequence",
181
+ sequenceId,
182
+ sequenceIndex: index + 1,
183
+ sequenceTotalRequested: maxImages,
184
+ sequenceTotalReturned: returned,
185
+ sequenceStatus: status,
186
+ stageLabel: String.fromCharCode(65 + index),
187
+ requestId,
188
+ prompt,
189
+ userPrompt: prompt,
190
+ revisedPrompt: image.revisedPrompt || null,
191
+ promptMode: normalizedPromptMode,
192
+ quality,
193
+ size: effectiveSize,
194
+ format,
195
+ moderation,
196
+ model: imageModel,
197
+ provider: activeProvider,
198
+ createdAt: Date.now(),
199
+ usage: generated.usage || null,
200
+ webSearchCalls: generated.webSearchCalls || 0,
201
+ webSearchEnabled,
202
+ refsCount: refCheck.refs.length,
203
+ };
204
+ const rawBuffer = Buffer.from(image.b64, "base64");
205
+ const embedded = await embedImageMetadataBestEffort(rawBuffer, format, meta, {
206
+ version: ctx.packageVersion,
207
+ });
208
+ await writeFile(join(ctx.config.storage.generatedDir, filename), embedded.buffer);
209
+ await writeFile(join(ctx.config.storage.generatedDir, filename + ".json"), JSON.stringify(meta)).catch(() => {});
210
+ const item = {
211
+ image: `data:${mime};base64,${image.b64}`,
212
+ filename,
213
+ revisedPrompt: image.revisedPrompt || null,
214
+ sequenceId,
215
+ sequenceIndex: index + 1,
216
+ sequenceTotalRequested: maxImages,
217
+ sequenceTotalReturned: returned,
218
+ sequenceStatus: status,
219
+ };
220
+ images.push(item);
221
+ sendSse(res, "image", item);
222
+ }
223
+
224
+ finishMeta = { sequenceId, imageCount: returned, maxImages, status };
225
+ finishHttpStatus = 200;
226
+ sendSse(res, "done", {
227
+ ok: true,
228
+ requestId,
229
+ sequenceId,
230
+ requested: maxImages,
231
+ returned,
232
+ status,
233
+ elapsed,
234
+ images,
235
+ provider: activeProvider,
236
+ quality,
237
+ size: effectiveSize,
238
+ moderation,
239
+ model: imageModel,
240
+ usage: generated.usage || null,
241
+ webSearchCalls: generated.webSearchCalls || 0,
242
+ webSearchEnabled,
243
+ warnings: qualityWarnings,
244
+ extraIgnored: generated.extraIgnored || 0,
245
+ promptMode: normalizedPromptMode,
246
+ });
247
+ logEvent("multimode", "saved", {
248
+ requestId,
249
+ sequenceId,
250
+ imageCount: returned,
251
+ maxImages,
252
+ status,
253
+ elapsedMs: Date.now() - startTime,
254
+ });
255
+ } catch (err) {
256
+ const fallbackCode = err.code || classifyUpstreamError(err.message);
257
+ finishStatus = "error";
258
+ finishHttpStatus = err.status || 500;
259
+ finishErrorCode = fallbackCode || "MULTIMODE_GENERATE_FAILED";
260
+ logError("multimode", "error", err, { requestId, code: finishErrorCode });
261
+ sendSse(res, "error", {
262
+ error: err.message,
263
+ code: finishErrorCode,
264
+ status: finishHttpStatus,
265
+ requestId,
266
+ upstreamCode: err.upstreamCode || null,
267
+ upstreamType: err.upstreamType || null,
268
+ upstreamParam: err.upstreamParam || null,
269
+ });
270
+ } finally {
271
+ finishJob(requestId, {
272
+ status: finishStatus,
273
+ httpStatus: finishHttpStatus,
274
+ errorCode: finishErrorCode,
275
+ meta: finishMeta,
276
+ });
277
+ res.end();
278
+ }
279
+ });
280
+ }