ima2-gen 1.1.8 → 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 (230) 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 -243
  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 +87 -93
  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 +125 -129
  130. package/lib/promptImport/curatedSources.ts +139 -0
  131. package/lib/promptImport/discoveryRegistry.js +185 -203
  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 +209 -219
  136. package/lib/promptImport/githubDiscovery.ts +248 -0
  137. package/lib/promptImport/githubFolder.js +253 -259
  138. package/lib/promptImport/githubFolder.ts +308 -0
  139. package/lib/promptImport/githubSource.js +189 -200
  140. package/lib/promptImport/githubSource.ts +239 -0
  141. package/lib/promptImport/gptImageHints.js +49 -56
  142. package/lib/promptImport/gptImageHints.ts +68 -0
  143. package/lib/promptImport/parsePromptCandidates.js +108 -123
  144. package/lib/promptImport/parsePromptCandidates.ts +153 -0
  145. package/lib/promptImport/promptIndex.js +190 -208
  146. package/lib/promptImport/promptIndex.ts +248 -0
  147. package/lib/promptImport/rankPromptCandidates.js +46 -43
  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 +27 -27
  187. package/routes/imageImport.ts +33 -0
  188. package/routes/index.js +17 -17
  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 +284 -324
  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 +2 -2
  219. package/assets/phase-a-bg-cleanup-test.png +0 -0
  220. package/assets/screenshot.png +0 -0
  221. package/assets/screenshots/classic-generate-light.png +0 -0
  222. package/assets/screenshots/node-graph-branching.png +0 -0
  223. package/assets/screenshots/settings-oauth-generation.png +0 -0
  224. package/assets/screenshots/settings-workspace.png +0 -0
  225. package/assets/screenshots/style-sheet-editor.png +0 -0
  226. package/integrations/comfyui/ima2_gen_bridge/__pycache__/__init__.cpython-313.pyc +0 -0
  227. package/integrations/comfyui/ima2_gen_bridge/__pycache__/nodes.cpython-313.pyc +0 -0
  228. package/ui/dist/assets/index-BDffwmLs.css +0 -1
  229. package/ui/dist/assets/index-D0fdHLkJ.js +0 -31
  230. package/ui/dist/assets/index-D0fdHLkJ.js.map +0 -1
@@ -0,0 +1,248 @@
1
+ import { createHash } from "node:crypto";
2
+ import { promptImportError } from "./errors.js";
3
+ import { upsertDiscoveryCandidates } from "./discoveryRegistry.js";
4
+
5
+ const GITHUB_API_HOST = "api.github.com";
6
+ const DEFAULT_DISCOVERY_SEEDS = [
7
+ "gpt-image-2 prompt",
8
+ "image generation prompts",
9
+ "nano banana prompts",
10
+ "product photography prompt",
11
+ "typography image prompt",
12
+ "reference image prompt",
13
+ ];
14
+
15
+ function tokenize(value) {
16
+ return String(value || "")
17
+ .toLowerCase()
18
+ .split(/[^a-z0-9가-힣-]+/i)
19
+ .filter(Boolean);
20
+ }
21
+
22
+ function discoveryLimits(ctx) {
23
+ return {
24
+ limit: ctx.config.limits.promptImportDiscoverySearchLimit,
25
+ maxQueries: ctx.config.limits.promptImportDiscoveryMaxQueries,
26
+ fetchTimeoutMs: ctx.config.limits.promptImportFetchTimeoutMs,
27
+ };
28
+ }
29
+
30
+ function validateGitHubApiUrl(rawUrl) {
31
+ let url;
32
+ try {
33
+ url = new URL(rawUrl);
34
+ } catch {
35
+ throw promptImportError("GITHUB_DISCOVERY_FAILED", "GitHub discovery returned an invalid URL");
36
+ }
37
+ if (!["https:", "http:"].includes(url.protocol) || url.hostname !== GITHUB_API_HOST) {
38
+ throw promptImportError("GITHUB_DISCOVERY_FAILED", "GitHub discovery redirected to an unsupported host");
39
+ }
40
+ }
41
+
42
+ function rateLimitFromHeaders(headers) {
43
+ const remaining = Number(headers.get("x-ratelimit-remaining") || Number.NaN);
44
+ const reset = Number(headers.get("x-ratelimit-reset") || Number.NaN);
45
+ const limit = Number(headers.get("x-ratelimit-limit") || Number.NaN);
46
+ return {
47
+ limit: Number.isFinite(limit) ? limit : null,
48
+ remaining: Number.isFinite(remaining) ? remaining : null,
49
+ resetAt: Number.isFinite(reset) ? new Date(reset * 1000).toISOString() : null,
50
+ };
51
+ }
52
+
53
+ function searchHeaders(ctx) {
54
+ const headers: any = {
55
+ Accept: "application/vnd.github+json",
56
+ "X-GitHub-Api-Version": "2022-11-28",
57
+ "User-Agent": "ima2-prompt-import-discovery",
58
+ };
59
+ const token = ctx.config.github?.token;
60
+ if (token) headers.Authorization = `Bearer ${token}`;
61
+ return headers;
62
+ }
63
+
64
+ export function buildDiscoveryQueries({ q = "", seeds = [], limit = 5 }: any = {}) {
65
+ const raw = [q, ...seeds, ...DEFAULT_DISCOVERY_SEEDS]
66
+ .map((item) => String(item || "").trim())
67
+ .filter(Boolean);
68
+ const unique = [...new Set(raw)];
69
+ if (unique.length === 0) {
70
+ throw promptImportError("GITHUB_DISCOVERY_QUERY_EMPTY", "Discovery query is required", 422);
71
+ }
72
+ return unique.slice(0, Math.max(1, Number(limit) || 1));
73
+ }
74
+
75
+ export function scoreDiscoveryRepository(repo, context: any = {}) {
76
+ const terms = tokenize([context.query, ...(context.seeds || [])].join(" "));
77
+ const nameText = `${repo.full_name || ""} ${repo.description || ""} ${(repo.topics || []).join(" ")}`.toLowerCase();
78
+ const pushedAt = repo.pushed_at ? Date.parse(repo.pushed_at) : 0;
79
+ const daysSincePush = pushedAt ? (Date.now() - pushedAt) / 86_400_000 : Number.POSITIVE_INFINITY;
80
+ const scoreReasons = [];
81
+ const warnings = [];
82
+ let score = 0;
83
+
84
+ const stars = Number(repo.stargazers_count || 0);
85
+ if (stars > 1000) {
86
+ score += 20;
87
+ scoreReasons.push("popular-repo");
88
+ } else if (stars > 100) {
89
+ score += 12;
90
+ scoreReasons.push("known-repo");
91
+ } else if (stars > 10) {
92
+ score += 5;
93
+ scoreReasons.push("some-stars");
94
+ }
95
+
96
+ if (daysSincePush <= 365) {
97
+ score += 10;
98
+ scoreReasons.push("recently-updated");
99
+ } else {
100
+ score -= 6;
101
+ warnings.push("stale-repo");
102
+ }
103
+
104
+ if (repo.license?.spdx_id) {
105
+ score += 8;
106
+ scoreReasons.push("license-present");
107
+ } else {
108
+ score -= 8;
109
+ warnings.push("no-license");
110
+ }
111
+
112
+ if (repo.archived || repo.disabled) {
113
+ score -= 20;
114
+ warnings.push("archived-or-disabled");
115
+ }
116
+ if (repo.fork) {
117
+ score -= 4;
118
+ warnings.push("fork-source");
119
+ }
120
+ if (!repo.default_branch) {
121
+ score -= 10;
122
+ warnings.push("missing-default-branch");
123
+ } else if (String(repo.default_branch).includes("/")) {
124
+ warnings.push("discovery-default-branch-unsupported");
125
+ }
126
+
127
+ const promptTerms = ["prompt", "image", "generation", "gpt-image", "nano", "typography", "reference"];
128
+ if (promptTerms.some((term) => nameText.includes(term))) {
129
+ score += 14;
130
+ scoreReasons.push("prompt-like");
131
+ }
132
+ for (const term of terms) {
133
+ if (term && nameText.includes(term)) score += 3;
134
+ }
135
+ if (!repo.html_url || !String(repo.html_url).startsWith("https://github.com/")) {
136
+ score -= 20;
137
+ warnings.push("non-github-url");
138
+ }
139
+
140
+ return { score, scoreReasons: [...new Set(scoreReasons)], warnings: [...new Set(warnings)] };
141
+ }
142
+
143
+ export function normalizeDiscoveryCandidate(repo, context: any = {}) {
144
+ const fullName = String(repo.full_name || "").trim();
145
+ const [owner, name] = fullName.split("/");
146
+ const scored = scoreDiscoveryRepository(repo, context);
147
+ return {
148
+ id: `github:${fullName}`,
149
+ repo: fullName,
150
+ owner,
151
+ name,
152
+ fullName,
153
+ htmlUrl: repo.html_url,
154
+ description: repo.description || "",
155
+ defaultBranch: repo.default_branch || "main",
156
+ stars: Number(repo.stargazers_count || 0),
157
+ forks: Number(repo.forks_count || 0),
158
+ openIssues: Number(repo.open_issues_count || 0),
159
+ updatedAt: repo.updated_at || null,
160
+ pushedAt: repo.pushed_at || null,
161
+ licenseSpdx: repo.license?.spdx_id || "NOASSERTION",
162
+ topics: Array.isArray(repo.topics) ? repo.topics : [],
163
+ language: repo.language || null,
164
+ score: scored.score,
165
+ scoreReasons: scored.scoreReasons,
166
+ warnings: scored.warnings,
167
+ status: "candidate",
168
+ query: context.query || "",
169
+ discoveredAt: new Date().toISOString(),
170
+ };
171
+ }
172
+
173
+ export function discoveryCacheKey(input) {
174
+ return createHash("sha256").update(JSON.stringify(input)).digest("hex");
175
+ }
176
+
177
+ async function searchOneQuery(ctx, query, perPage) {
178
+ const controller = new AbortController();
179
+ const timer = setTimeout(() => controller.abort(), discoveryLimits(ctx).fetchTimeoutMs);
180
+ const url = new URL("https://api.github.com/search/repositories");
181
+ url.searchParams.set("q", `${query} in:name,description`);
182
+ url.searchParams.set("sort", "stars");
183
+ url.searchParams.set("order", "desc");
184
+ url.searchParams.set("per_page", String(perPage));
185
+ try {
186
+ const response = await fetch(url, {
187
+ headers: searchHeaders(ctx),
188
+ signal: controller.signal,
189
+ });
190
+ validateGitHubApiUrl(response.url);
191
+ const rateLimit = rateLimitFromHeaders(response.headers);
192
+ if (response.status === 403 || response.status === 429) {
193
+ throw promptImportError("GITHUB_RATE_LIMITED", "GitHub discovery rate limit reached", 429);
194
+ }
195
+ if (!response.ok) {
196
+ throw promptImportError("GITHUB_DISCOVERY_FAILED", `GitHub discovery failed with ${response.status}`, 422);
197
+ }
198
+ const data: any = await response.json();
199
+ const items = Array.isArray(data.items) ? data.items : [];
200
+ return { items, rateLimit };
201
+ } catch (error) {
202
+ if (error?.name === "AbortError") {
203
+ throw promptImportError("REMOTE_FETCH_TIMEOUT", "GitHub discovery timed out", 504);
204
+ }
205
+ throw error;
206
+ } finally {
207
+ clearTimeout(timer);
208
+ }
209
+ }
210
+
211
+ export async function searchGitHubDiscovery(ctx, options: any = {}) {
212
+ const limits = discoveryLimits(ctx);
213
+ const queryLimit = Math.min(Number(options.maxQueries) || limits.maxQueries, limits.maxQueries);
214
+ const queries = buildDiscoveryQueries({
215
+ q: options.q,
216
+ seeds: options.seeds,
217
+ limit: queryLimit,
218
+ });
219
+ const requestedLimit = Math.min(Number(options.limit) || limits.limit, limits.limit);
220
+ const perQuery = Math.max(1, Math.ceil(requestedLimit / queries.length));
221
+ const warnings = [];
222
+ let rateLimit = null;
223
+ const byRepo = new Map();
224
+
225
+ for (const query of queries) {
226
+ const result = await searchOneQuery(ctx, query, perQuery);
227
+ rateLimit = result.rateLimit;
228
+ for (const repo of result.items) {
229
+ const candidate = normalizeDiscoveryCandidate(repo, {
230
+ query,
231
+ seeds: options.seeds,
232
+ });
233
+ const existing = byRepo.get(candidate.fullName);
234
+ if (!existing || candidate.score > existing.score) {
235
+ byRepo.set(candidate.fullName, candidate);
236
+ }
237
+ }
238
+ }
239
+
240
+ const candidates = [...byRepo.values()]
241
+ .filter((candidate) => candidate.fullName && candidate.htmlUrl?.startsWith("https://github.com/"))
242
+ .sort((a, b) => b.score - a.score || b.stars - a.stars)
243
+ .slice(0, requestedLimit);
244
+
245
+ await upsertDiscoveryCandidates(ctx, candidates);
246
+ if (rateLimit?.remaining === 0) warnings.push("github-rate-limit-exhausted");
247
+ return { candidates, warnings, rateLimit, cacheKey: discoveryCacheKey({ queries, requestedLimit }) };
248
+ }