@enslo/sd-metadata 1.5.0 → 1.6.1
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.ja.md +1 -1
- package/README.md +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +397 -301
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4,6 +4,14 @@ var Result = {
|
|
|
4
4
|
error: (error) => ({ ok: false, error })
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
+
// src/utils/object.ts
|
|
8
|
+
function trimObject(obj) {
|
|
9
|
+
const result = Object.fromEntries(
|
|
10
|
+
Object.entries(obj).filter(([, value]) => value !== void 0)
|
|
11
|
+
);
|
|
12
|
+
return Object.keys(result).length === 0 ? void 0 : result;
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
// src/parsers/a1111.ts
|
|
8
16
|
function parseA1111(entries) {
|
|
9
17
|
const parametersEntry = entries.find(
|
|
@@ -24,21 +32,8 @@ function parseA1111(entries) {
|
|
|
24
32
|
const version = settingsMap.get("Version");
|
|
25
33
|
const app = settingsMap.get("App");
|
|
26
34
|
const software = detectSoftwareVariant(version, app);
|
|
27
|
-
const metadata = {
|
|
28
|
-
software,
|
|
29
|
-
prompt,
|
|
30
|
-
negativePrompt,
|
|
31
|
-
width,
|
|
32
|
-
height
|
|
33
|
-
};
|
|
34
35
|
const modelName = settingsMap.get("Model");
|
|
35
36
|
const modelHash = settingsMap.get("Model hash");
|
|
36
|
-
if (modelName || modelHash) {
|
|
37
|
-
metadata.model = {
|
|
38
|
-
name: modelName,
|
|
39
|
-
hash: modelHash
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
37
|
const sampler = settingsMap.get("Sampler");
|
|
43
38
|
const scheduler = settingsMap.get("Schedule type");
|
|
44
39
|
const steps = parseNumber(settingsMap.get("Steps"));
|
|
@@ -47,29 +42,30 @@ function parseA1111(entries) {
|
|
|
47
42
|
);
|
|
48
43
|
const seed = parseNumber(settingsMap.get("Seed"));
|
|
49
44
|
const clipSkip = parseNumber(settingsMap.get("Clip skip"));
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const hiresScale = parseNumber(settingsMap.get("Hires upscale"));
|
|
46
|
+
const upscaler = settingsMap.get("Hires upscaler");
|
|
47
|
+
const hiresSteps = parseNumber(settingsMap.get("Hires steps"));
|
|
48
|
+
const denoise = parseNumber(settingsMap.get("Denoising strength"));
|
|
49
|
+
const hiresSize = settingsMap.get("Hires size");
|
|
50
|
+
const [hiresWidth] = parseSize(hiresSize ?? "");
|
|
51
|
+
const scale = hiresScale ?? (hiresWidth > 0 ? hiresWidth / width : void 0);
|
|
52
|
+
return Result.ok({
|
|
53
|
+
software,
|
|
54
|
+
prompt,
|
|
55
|
+
negativePrompt,
|
|
56
|
+
width,
|
|
57
|
+
height,
|
|
58
|
+
model: trimObject({ name: modelName, hash: modelHash }),
|
|
59
|
+
sampling: trimObject({
|
|
52
60
|
sampler,
|
|
53
61
|
scheduler,
|
|
54
62
|
steps,
|
|
55
63
|
cfg,
|
|
56
64
|
seed,
|
|
57
65
|
clipSkip
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const upscaler = settingsMap.get("Hires upscaler");
|
|
62
|
-
const hiresSteps = parseNumber(settingsMap.get("Hires steps"));
|
|
63
|
-
const denoise = parseNumber(settingsMap.get("Denoising strength"));
|
|
64
|
-
const hiresSize = settingsMap.get("Hires size");
|
|
65
|
-
if ([hiresScale, hiresSize, upscaler, hiresSteps, denoise].some(
|
|
66
|
-
(v) => v !== void 0
|
|
67
|
-
)) {
|
|
68
|
-
const [hiresWidth] = parseSize(hiresSize ?? "");
|
|
69
|
-
const scale = hiresScale ?? hiresWidth / width;
|
|
70
|
-
metadata.hires = { scale, upscaler, steps: hiresSteps, denoise };
|
|
71
|
-
}
|
|
72
|
-
return Result.ok(metadata);
|
|
66
|
+
}),
|
|
67
|
+
hires: trimObject({ scale, upscaler, steps: hiresSteps, denoise })
|
|
68
|
+
});
|
|
73
69
|
}
|
|
74
70
|
function parseParametersText(text) {
|
|
75
71
|
const negativeIndex = text.indexOf("Negative prompt:");
|
|
@@ -133,13 +129,6 @@ function detectSoftwareVariant(version, app) {
|
|
|
133
129
|
return "sd-webui";
|
|
134
130
|
}
|
|
135
131
|
|
|
136
|
-
// src/utils/entries.ts
|
|
137
|
-
function buildEntryRecord(entries) {
|
|
138
|
-
return Object.freeze(
|
|
139
|
-
Object.fromEntries(entries.map((e) => [e.keyword, e.text]))
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
132
|
// src/utils/json.ts
|
|
144
133
|
function parseJson(text) {
|
|
145
134
|
try {
|
|
@@ -152,7 +141,37 @@ function parseJson(text) {
|
|
|
152
141
|
}
|
|
153
142
|
}
|
|
154
143
|
|
|
144
|
+
// src/utils/entries.ts
|
|
145
|
+
function buildEntryRecord(entries) {
|
|
146
|
+
return Object.freeze(
|
|
147
|
+
Object.fromEntries(entries.map((e) => [e.keyword, e.text]))
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
function extractFromCommentJson(entryRecord, key) {
|
|
151
|
+
if (!entryRecord.Comment?.startsWith("{")) return void 0;
|
|
152
|
+
const parsed = parseJson(entryRecord.Comment);
|
|
153
|
+
if (!parsed.ok) return void 0;
|
|
154
|
+
const value = parsed.value[key];
|
|
155
|
+
if (typeof value === "string") return value;
|
|
156
|
+
if (typeof value === "object" && value !== null) return JSON.stringify(value);
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
155
160
|
// src/parsers/comfyui.ts
|
|
161
|
+
var CIVITAI_EXTENSION_KEYS = ["extra", "extraMetadata", "resource-stack"];
|
|
162
|
+
var COMFYUI_NODE_KEYS = {
|
|
163
|
+
sampler: ["Sampler"],
|
|
164
|
+
positiveClip: ["PositiveCLIP_Base"],
|
|
165
|
+
negativeClip: ["NegativeCLIP_Base"],
|
|
166
|
+
latentImage: ["EmptyLatentImage"],
|
|
167
|
+
checkpoint: ["CheckpointLoader_Base"],
|
|
168
|
+
hiresModelUpscale: [
|
|
169
|
+
"HiresFix_ModelUpscale_UpscaleModelLoader",
|
|
170
|
+
"PostUpscale_ModelUpscale_UpscaleModelLoader"
|
|
171
|
+
],
|
|
172
|
+
hiresImageScale: ["HiresFix_ImageScale", "PostUpscale_ImageScale"],
|
|
173
|
+
hiresSampler: ["HiresFix_Sampler"]
|
|
174
|
+
};
|
|
156
175
|
function parseComfyUI(entries) {
|
|
157
176
|
const entryRecord = buildEntryRecord(entries);
|
|
158
177
|
const promptText = findPromptJson(entryRecord);
|
|
@@ -167,99 +186,35 @@ function parseComfyUI(entries) {
|
|
|
167
186
|
});
|
|
168
187
|
}
|
|
169
188
|
const prompt = parsed.value;
|
|
170
|
-
|
|
171
|
-
if (!nodes.some((node) => "class_type" in node)) {
|
|
189
|
+
if (!Object.values(prompt).some((node) => "class_type" in node)) {
|
|
172
190
|
return Result.error({ type: "unsupportedFormat" });
|
|
173
191
|
}
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
const width = latentWidth || extraMeta?.width || 0;
|
|
186
|
-
const height = latentHeight || extraMeta?.height || 0;
|
|
187
|
-
const metadata = {
|
|
192
|
+
const nodes = Object.fromEntries(
|
|
193
|
+
Object.entries(prompt).filter(
|
|
194
|
+
([key]) => !CIVITAI_EXTENSION_KEYS.includes(key)
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
const comfyMetadata = extractComfyUIMetadata(prompt);
|
|
198
|
+
const civitaiMetadata = extractCivitaiMetadata(
|
|
199
|
+
extractExtraMetadata(prompt, entryRecord)
|
|
200
|
+
);
|
|
201
|
+
const merged = mergeMetadata(civitaiMetadata, comfyMetadata);
|
|
202
|
+
return Result.ok({
|
|
188
203
|
software: "comfyui",
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
} else if (extraMeta?.baseModel) {
|
|
200
|
-
metadata.model = { name: extraMeta.baseModel };
|
|
201
|
-
}
|
|
202
|
-
if (ksampler) {
|
|
203
|
-
metadata.sampling = {
|
|
204
|
-
seed: ksampler.inputs.seed,
|
|
205
|
-
steps: ksampler.inputs.steps,
|
|
206
|
-
cfg: ksampler.inputs.cfg,
|
|
207
|
-
sampler: ksampler.inputs.sampler_name,
|
|
208
|
-
scheduler: ksampler.inputs.scheduler
|
|
209
|
-
};
|
|
210
|
-
} else if (extraMeta) {
|
|
211
|
-
metadata.sampling = {
|
|
212
|
-
seed: extraMeta.seed,
|
|
213
|
-
steps: extraMeta.steps,
|
|
214
|
-
cfg: extraMeta.cfgScale,
|
|
215
|
-
sampler: extraMeta.sampler
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
const hiresModel = findNode(prompt, [
|
|
219
|
-
"HiresFix_ModelUpscale_UpscaleModelLoader",
|
|
220
|
-
"PostUpscale_ModelUpscale_UpscaleModelLoader"
|
|
221
|
-
])?.inputs;
|
|
222
|
-
const hiresScale = findNode(prompt, [
|
|
223
|
-
"HiresFix_ImageScale",
|
|
224
|
-
"PostUpscale_ImageScale"
|
|
225
|
-
])?.inputs;
|
|
226
|
-
const hiresSampler = findNode(prompt, ["HiresFix_Sampler"])?.inputs;
|
|
227
|
-
if (hiresModel && hiresScale) {
|
|
228
|
-
const hiresWidth = hiresScale.width;
|
|
229
|
-
const scale = latentWidth > 0 ? Math.round(hiresWidth / latentWidth * 100) / 100 : void 0;
|
|
230
|
-
if (hiresSampler) {
|
|
231
|
-
metadata.hires = {
|
|
232
|
-
upscaler: hiresModel.model_name,
|
|
233
|
-
scale,
|
|
234
|
-
steps: hiresSampler.steps,
|
|
235
|
-
denoise: hiresSampler.denoise
|
|
236
|
-
};
|
|
237
|
-
} else {
|
|
238
|
-
metadata.upscale = {
|
|
239
|
-
upscaler: hiresModel.model_name,
|
|
240
|
-
scale
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (extraMeta?.transformations) {
|
|
245
|
-
const upscaleTransform = extraMeta.transformations.find(
|
|
246
|
-
(t) => t.type === "upscale"
|
|
247
|
-
);
|
|
248
|
-
if (upscaleTransform) {
|
|
249
|
-
const originalWidth = extraMeta.width ?? width;
|
|
250
|
-
if (originalWidth > 0 && upscaleTransform.upscaleWidth) {
|
|
251
|
-
const scale = upscaleTransform.upscaleWidth / originalWidth;
|
|
252
|
-
metadata.upscale = {
|
|
253
|
-
scale: Math.round(scale * 100) / 100
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return Result.ok(metadata);
|
|
204
|
+
nodes,
|
|
205
|
+
...merged
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function cleanJsonString(json) {
|
|
209
|
+
return json.replace(/\0+$/, "").replace(/:\s*NaN\b/g, ": null");
|
|
210
|
+
}
|
|
211
|
+
function calculateScale(targetWidth, baseWidth) {
|
|
212
|
+
if (baseWidth <= 0 || targetWidth <= 0) return void 0;
|
|
213
|
+
return Math.round(targetWidth / baseWidth * 100) / 100;
|
|
259
214
|
}
|
|
260
215
|
function findPromptJson(entryRecord) {
|
|
261
216
|
if (entryRecord.prompt) {
|
|
262
|
-
return entryRecord.prompt
|
|
217
|
+
return cleanJsonString(entryRecord.prompt);
|
|
263
218
|
}
|
|
264
219
|
const candidates = [
|
|
265
220
|
entryRecord.Comment,
|
|
@@ -273,7 +228,7 @@ function findPromptJson(entryRecord) {
|
|
|
273
228
|
for (const candidate of candidates) {
|
|
274
229
|
if (!candidate) continue;
|
|
275
230
|
if (candidate.startsWith("{")) {
|
|
276
|
-
const cleaned = candidate
|
|
231
|
+
const cleaned = cleanJsonString(candidate);
|
|
277
232
|
const parsed = parseJson(cleaned);
|
|
278
233
|
if (!parsed.ok) continue;
|
|
279
234
|
if (parsed.value.prompt && typeof parsed.value.prompt === "object") {
|
|
@@ -293,14 +248,174 @@ function findNode(prompt, keys) {
|
|
|
293
248
|
function extractText(node) {
|
|
294
249
|
return typeof node?.inputs.text === "string" ? node.inputs.text : "";
|
|
295
250
|
}
|
|
296
|
-
function
|
|
251
|
+
function extractPromptTexts(prompt) {
|
|
252
|
+
const positiveClip = findNode(prompt, COMFYUI_NODE_KEYS.positiveClip);
|
|
253
|
+
const negativeClip = findNode(prompt, COMFYUI_NODE_KEYS.negativeClip);
|
|
254
|
+
return {
|
|
255
|
+
promptText: extractText(positiveClip),
|
|
256
|
+
negativeText: extractText(negativeClip)
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function extractDimensions(prompt) {
|
|
260
|
+
const latentImage = findNode(prompt, COMFYUI_NODE_KEYS.latentImage);
|
|
261
|
+
return {
|
|
262
|
+
width: latentImage ? Number(latentImage.inputs.width) || 0 : 0,
|
|
263
|
+
height: latentImage ? Number(latentImage.inputs.height) || 0 : 0
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function extractSamplingFromKSampler(ksampler) {
|
|
267
|
+
if (!ksampler) return void 0;
|
|
268
|
+
return {
|
|
269
|
+
seed: ksampler.inputs.seed,
|
|
270
|
+
steps: ksampler.inputs.steps,
|
|
271
|
+
cfg: ksampler.inputs.cfg,
|
|
272
|
+
sampler: ksampler.inputs.sampler_name,
|
|
273
|
+
scheduler: ksampler.inputs.scheduler
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function extractModelFromCheckpoint(checkpoint) {
|
|
277
|
+
if (!checkpoint?.inputs?.ckpt_name) return void 0;
|
|
278
|
+
return { name: String(checkpoint.inputs.ckpt_name) };
|
|
279
|
+
}
|
|
280
|
+
function extractComfyUIMetadata(prompt) {
|
|
281
|
+
const { promptText, negativeText } = extractPromptTexts(prompt);
|
|
282
|
+
const { width, height } = extractDimensions(prompt);
|
|
283
|
+
const ksampler = findNode(prompt, COMFYUI_NODE_KEYS.sampler);
|
|
284
|
+
const checkpoint = findNode(prompt, COMFYUI_NODE_KEYS.checkpoint);
|
|
285
|
+
const hiresModel = findNode(
|
|
286
|
+
prompt,
|
|
287
|
+
COMFYUI_NODE_KEYS.hiresModelUpscale
|
|
288
|
+
)?.inputs;
|
|
289
|
+
const hiresScale = findNode(
|
|
290
|
+
prompt,
|
|
291
|
+
COMFYUI_NODE_KEYS.hiresImageScale
|
|
292
|
+
)?.inputs;
|
|
293
|
+
const hiresSampler = findNode(prompt, COMFYUI_NODE_KEYS.hiresSampler)?.inputs;
|
|
294
|
+
return trimObject({
|
|
295
|
+
prompt: promptText || void 0,
|
|
296
|
+
negativePrompt: negativeText || void 0,
|
|
297
|
+
width: width > 0 ? width : void 0,
|
|
298
|
+
height: height > 0 ? height : void 0,
|
|
299
|
+
model: extractModelFromCheckpoint(checkpoint),
|
|
300
|
+
sampling: extractSamplingFromKSampler(ksampler),
|
|
301
|
+
...buildHiresOrUpscale(hiresModel, hiresScale, hiresSampler, width)
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function buildHiresOrUpscale(hiresModel, hiresScale, hiresSampler, baseWidth) {
|
|
305
|
+
if (!hiresModel || !hiresScale) return {};
|
|
306
|
+
const hiresWidth = hiresScale.width;
|
|
307
|
+
const scale = calculateScale(hiresWidth, baseWidth);
|
|
308
|
+
if (hiresSampler) {
|
|
309
|
+
return {
|
|
310
|
+
hires: {
|
|
311
|
+
upscaler: hiresModel.model_name,
|
|
312
|
+
scale,
|
|
313
|
+
steps: hiresSampler.steps,
|
|
314
|
+
denoise: hiresSampler.denoise
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
upscale: {
|
|
320
|
+
upscaler: hiresModel.model_name,
|
|
321
|
+
scale
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function extractExtraMetadata(prompt, entryRecord) {
|
|
297
326
|
const extraMetaField = prompt.extraMetadata;
|
|
298
|
-
if (typeof extraMetaField
|
|
299
|
-
|
|
300
|
-
|
|
327
|
+
if (typeof extraMetaField === "string") {
|
|
328
|
+
const parsed = parseJson(extraMetaField);
|
|
329
|
+
if (parsed.ok) return parsed.value;
|
|
330
|
+
}
|
|
331
|
+
if (entryRecord?.extraMetadata) {
|
|
332
|
+
const parsed = parseJson(entryRecord.extraMetadata);
|
|
333
|
+
if (parsed.ok) return parsed.value;
|
|
334
|
+
}
|
|
335
|
+
return void 0;
|
|
336
|
+
}
|
|
337
|
+
function extractCivitaiMetadata(extraMeta) {
|
|
338
|
+
if (!extraMeta) return void 0;
|
|
339
|
+
const upscale = buildCivitaiUpscale(extraMeta);
|
|
340
|
+
const sampling = buildCivitaiSampling(extraMeta);
|
|
341
|
+
return trimObject({
|
|
342
|
+
prompt: extraMeta.prompt,
|
|
343
|
+
negativePrompt: extraMeta.negativePrompt,
|
|
344
|
+
width: extraMeta.width,
|
|
345
|
+
height: extraMeta.height,
|
|
346
|
+
model: extraMeta.baseModel ? { name: extraMeta.baseModel } : void 0,
|
|
347
|
+
...sampling,
|
|
348
|
+
...upscale
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
function buildCivitaiUpscale(extraMeta) {
|
|
352
|
+
if (!extraMeta.transformations) return {};
|
|
353
|
+
const upscaleTransform = extraMeta.transformations.find(
|
|
354
|
+
(t) => t.type === "upscale"
|
|
355
|
+
);
|
|
356
|
+
if (!upscaleTransform?.upscaleWidth) return {};
|
|
357
|
+
const scale = calculateScale(
|
|
358
|
+
upscaleTransform.upscaleWidth,
|
|
359
|
+
extraMeta.width ?? 0
|
|
360
|
+
);
|
|
361
|
+
if (scale === void 0) return {};
|
|
362
|
+
return {
|
|
363
|
+
upscale: { scale }
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function buildCivitaiSampling(extraMeta) {
|
|
367
|
+
if (extraMeta.seed === void 0 && extraMeta.steps === void 0 && extraMeta.cfgScale === void 0 && extraMeta.sampler === void 0) {
|
|
368
|
+
return {};
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
sampling: {
|
|
372
|
+
seed: extraMeta.seed,
|
|
373
|
+
steps: extraMeta.steps,
|
|
374
|
+
cfg: extraMeta.cfgScale,
|
|
375
|
+
sampler: extraMeta.sampler
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function mergeMetadata(base, override) {
|
|
380
|
+
const merged = { ...base, ...override };
|
|
381
|
+
return {
|
|
382
|
+
// Required fields with defaults
|
|
383
|
+
prompt: merged.prompt ?? "",
|
|
384
|
+
negativePrompt: merged.negativePrompt ?? "",
|
|
385
|
+
width: merged.width ?? 0,
|
|
386
|
+
height: merged.height ?? 0,
|
|
387
|
+
// Optional fields - only include if defined
|
|
388
|
+
...trimObject({
|
|
389
|
+
model: merged.model,
|
|
390
|
+
sampling: merged.sampling,
|
|
391
|
+
hires: merged.hires,
|
|
392
|
+
upscale: merged.upscale
|
|
393
|
+
})
|
|
394
|
+
};
|
|
301
395
|
}
|
|
302
396
|
|
|
303
397
|
// src/parsers/detect.ts
|
|
398
|
+
var MARKERS = {
|
|
399
|
+
// Unique chunk keywords
|
|
400
|
+
INVOKEAI: "invokeai_metadata",
|
|
401
|
+
TENSORART: "generation_data",
|
|
402
|
+
STABILITY_MATRIX: "smproj",
|
|
403
|
+
EASYDIFFUSION: "use_stable_diffusion_model",
|
|
404
|
+
CIVITAI_EXTRA: "extraMetadata",
|
|
405
|
+
// Content patterns
|
|
406
|
+
SWARMUI: "sui_image_params",
|
|
407
|
+
SWARM_VERSION: "swarm_version",
|
|
408
|
+
COMFYUI_NODE: "class_type",
|
|
409
|
+
NOVELAI_SCHEDULE: "noise_schedule",
|
|
410
|
+
NOVELAI_V4: "v4_prompt",
|
|
411
|
+
NOVELAI_UNCOND: "uncond_scale",
|
|
412
|
+
CIVITAI_NS: "civitai:",
|
|
413
|
+
CIVITAI_RESOURCES: "Civitai resources:",
|
|
414
|
+
RUINED_FOOOCUS: "RuinedFooocus",
|
|
415
|
+
HF_MODEL: '"Model"',
|
|
416
|
+
HF_RESOLUTION: '"resolution"',
|
|
417
|
+
FOOOCUS_BASE: '"base_model"'
|
|
418
|
+
};
|
|
304
419
|
function detectSoftware(entries) {
|
|
305
420
|
const entryRecord = buildEntryRecord(entries);
|
|
306
421
|
const uniqueResult = detectUniqueKeywords(entryRecord);
|
|
@@ -317,20 +432,23 @@ function detectUniqueKeywords(entryRecord) {
|
|
|
317
432
|
if (entryRecord.Software?.startsWith("NovelAI")) {
|
|
318
433
|
return "novelai";
|
|
319
434
|
}
|
|
320
|
-
if (
|
|
435
|
+
if (MARKERS.INVOKEAI in entryRecord) {
|
|
321
436
|
return "invokeai";
|
|
322
437
|
}
|
|
323
|
-
if (
|
|
438
|
+
if (MARKERS.TENSORART in entryRecord) {
|
|
324
439
|
return "tensorart";
|
|
325
440
|
}
|
|
326
|
-
if (
|
|
441
|
+
if (MARKERS.STABILITY_MATRIX in entryRecord) {
|
|
327
442
|
return "stability-matrix";
|
|
328
443
|
}
|
|
329
444
|
if ("negative_prompt" in entryRecord || "Negative Prompt" in entryRecord) {
|
|
330
445
|
return "easydiffusion";
|
|
331
446
|
}
|
|
447
|
+
if (MARKERS.CIVITAI_EXTRA in entryRecord) {
|
|
448
|
+
return "civitai";
|
|
449
|
+
}
|
|
332
450
|
const parameters = entryRecord.parameters;
|
|
333
|
-
if (parameters?.includes(
|
|
451
|
+
if (parameters?.includes(MARKERS.SWARMUI)) {
|
|
334
452
|
return "swarmui";
|
|
335
453
|
}
|
|
336
454
|
const comment = entryRecord.Comment;
|
|
@@ -342,15 +460,18 @@ function detectUniqueKeywords(entryRecord) {
|
|
|
342
460
|
function detectFromCommentJson(comment) {
|
|
343
461
|
try {
|
|
344
462
|
const parsed = JSON.parse(comment);
|
|
345
|
-
if (
|
|
463
|
+
if (MARKERS.INVOKEAI in parsed) {
|
|
346
464
|
return "invokeai";
|
|
347
465
|
}
|
|
348
|
-
if (
|
|
466
|
+
if (MARKERS.TENSORART in parsed) {
|
|
349
467
|
return "tensorart";
|
|
350
468
|
}
|
|
351
|
-
if (
|
|
469
|
+
if (MARKERS.STABILITY_MATRIX in parsed) {
|
|
352
470
|
return "stability-matrix";
|
|
353
471
|
}
|
|
472
|
+
if (MARKERS.CIVITAI_EXTRA in parsed) {
|
|
473
|
+
return "civitai";
|
|
474
|
+
}
|
|
354
475
|
if ("prompt" in parsed && "workflow" in parsed) {
|
|
355
476
|
const workflow = parsed.workflow;
|
|
356
477
|
const prompt = parsed.prompt;
|
|
@@ -360,12 +481,12 @@ function detectFromCommentJson(comment) {
|
|
|
360
481
|
return "comfyui";
|
|
361
482
|
}
|
|
362
483
|
}
|
|
363
|
-
if (
|
|
484
|
+
if (MARKERS.SWARMUI in parsed) {
|
|
364
485
|
return "swarmui";
|
|
365
486
|
}
|
|
366
487
|
if ("prompt" in parsed && "parameters" in parsed) {
|
|
367
488
|
const params = String(parsed.parameters || "");
|
|
368
|
-
if (params.includes(
|
|
489
|
+
if (params.includes(MARKERS.SWARMUI) || params.includes(MARKERS.SWARM_VERSION)) {
|
|
369
490
|
return "swarmui";
|
|
370
491
|
}
|
|
371
492
|
}
|
|
@@ -383,10 +504,13 @@ function detectComfyUIEntries(entryRecord) {
|
|
|
383
504
|
if ("prompt" in entryRecord) {
|
|
384
505
|
const promptText = entryRecord.prompt;
|
|
385
506
|
if (promptText?.startsWith("{")) {
|
|
386
|
-
if (promptText.includes(
|
|
507
|
+
if (promptText.includes(MARKERS.SWARMUI)) {
|
|
387
508
|
return "swarmui";
|
|
388
509
|
}
|
|
389
|
-
if (promptText.includes("
|
|
510
|
+
if (promptText.includes(`"${MARKERS.CIVITAI_EXTRA}"`)) {
|
|
511
|
+
return "civitai";
|
|
512
|
+
}
|
|
513
|
+
if (promptText.includes(MARKERS.COMFYUI_NODE)) {
|
|
390
514
|
return "comfyui";
|
|
391
515
|
}
|
|
392
516
|
}
|
|
@@ -400,25 +524,25 @@ function detectFromTextContent(text) {
|
|
|
400
524
|
return detectFromA1111Format(text);
|
|
401
525
|
}
|
|
402
526
|
function detectFromJsonFormat(json) {
|
|
403
|
-
if (json.includes(
|
|
527
|
+
if (json.includes(MARKERS.SWARMUI)) {
|
|
404
528
|
return "swarmui";
|
|
405
529
|
}
|
|
406
|
-
if (json.includes(
|
|
530
|
+
if (json.includes(`"software":"${MARKERS.RUINED_FOOOCUS}"`) || json.includes(`"software": "${MARKERS.RUINED_FOOOCUS}"`)) {
|
|
407
531
|
return "ruined-fooocus";
|
|
408
532
|
}
|
|
409
|
-
if (json.includes(
|
|
533
|
+
if (json.includes(`"${MARKERS.EASYDIFFUSION}"`)) {
|
|
410
534
|
return "easydiffusion";
|
|
411
535
|
}
|
|
412
|
-
if (json.includes(
|
|
536
|
+
if (json.includes(MARKERS.CIVITAI_NS) || json.includes(`"${MARKERS.CIVITAI_EXTRA}"`)) {
|
|
413
537
|
return "civitai";
|
|
414
538
|
}
|
|
415
|
-
if (json.includes(
|
|
539
|
+
if (json.includes(`"${MARKERS.NOVELAI_V4}"`) || json.includes(`"${MARKERS.NOVELAI_SCHEDULE}"`) || json.includes(`"${MARKERS.NOVELAI_UNCOND}"`) || json.includes('"Software":"NovelAI"') || json.includes(`\\"${MARKERS.NOVELAI_SCHEDULE}\\"`) || json.includes(`\\"${MARKERS.NOVELAI_V4}\\"`)) {
|
|
416
540
|
return "novelai";
|
|
417
541
|
}
|
|
418
|
-
if (json.includes(
|
|
542
|
+
if (json.includes(MARKERS.HF_MODEL) && json.includes(MARKERS.HF_RESOLUTION)) {
|
|
419
543
|
return "hf-space";
|
|
420
544
|
}
|
|
421
|
-
if (json.includes('"prompt"') && json.includes(
|
|
545
|
+
if (json.includes('"prompt"') && json.includes(MARKERS.FOOOCUS_BASE)) {
|
|
422
546
|
return "fooocus";
|
|
423
547
|
}
|
|
424
548
|
if (json.includes('"prompt"') || json.includes('"nodes"')) {
|
|
@@ -427,7 +551,7 @@ function detectFromJsonFormat(json) {
|
|
|
427
551
|
return null;
|
|
428
552
|
}
|
|
429
553
|
function detectFromA1111Format(text) {
|
|
430
|
-
if (text.includes(
|
|
554
|
+
if (text.includes(MARKERS.SWARMUI) || text.includes(MARKERS.SWARM_VERSION)) {
|
|
431
555
|
return "swarmui";
|
|
432
556
|
}
|
|
433
557
|
const versionMatch = text.match(/Version:\s*([^\s,]+)/);
|
|
@@ -446,7 +570,7 @@ function detectFromA1111Format(text) {
|
|
|
446
570
|
if (text.includes("App: SD.Next") || text.includes("App:SD.Next")) {
|
|
447
571
|
return "sd-next";
|
|
448
572
|
}
|
|
449
|
-
if (text.includes(
|
|
573
|
+
if (text.includes(MARKERS.CIVITAI_RESOURCES)) {
|
|
450
574
|
return "civitai";
|
|
451
575
|
}
|
|
452
576
|
if (text.includes("Steps:") && text.includes("Sampler:")) {
|
|
@@ -606,33 +730,23 @@ function parseHfSpace(entries) {
|
|
|
606
730
|
negativePrompt: json.negative_prompt ?? "",
|
|
607
731
|
width,
|
|
608
732
|
height,
|
|
609
|
-
model: {
|
|
733
|
+
model: trimObject({
|
|
610
734
|
name: json.Model,
|
|
611
735
|
hash: json["Model hash"]
|
|
612
|
-
},
|
|
613
|
-
sampling: {
|
|
736
|
+
}),
|
|
737
|
+
sampling: trimObject({
|
|
614
738
|
sampler: json.sampler,
|
|
615
739
|
steps: json.num_inference_steps,
|
|
616
740
|
cfg: json.guidance_scale,
|
|
617
741
|
seed: json.seed
|
|
618
|
-
}
|
|
742
|
+
})
|
|
619
743
|
};
|
|
620
744
|
return Result.ok(metadata);
|
|
621
745
|
}
|
|
622
746
|
|
|
623
747
|
// src/parsers/invokeai.ts
|
|
624
748
|
function extractInvokeAIMetadata(entryRecord) {
|
|
625
|
-
|
|
626
|
-
return entryRecord.invokeai_metadata;
|
|
627
|
-
}
|
|
628
|
-
if (!entryRecord.Comment) {
|
|
629
|
-
return void 0;
|
|
630
|
-
}
|
|
631
|
-
const commentParsed = parseJson(entryRecord.Comment);
|
|
632
|
-
if (!commentParsed.ok || !("invokeai_metadata" in commentParsed.value)) {
|
|
633
|
-
return void 0;
|
|
634
|
-
}
|
|
635
|
-
return JSON.stringify(commentParsed.value.invokeai_metadata);
|
|
749
|
+
return entryRecord.invokeai_metadata ?? extractFromCommentJson(entryRecord, "invokeai_metadata");
|
|
636
750
|
}
|
|
637
751
|
function parseInvokeAI(entries) {
|
|
638
752
|
const entryRecord = buildEntryRecord(entries);
|
|
@@ -650,28 +764,23 @@ function parseInvokeAI(entries) {
|
|
|
650
764
|
const data = parsed.value;
|
|
651
765
|
const width = data.width ?? 0;
|
|
652
766
|
const height = data.height ?? 0;
|
|
653
|
-
|
|
767
|
+
return Result.ok({
|
|
654
768
|
software: "invokeai",
|
|
655
769
|
prompt: data.positive_prompt ?? "",
|
|
656
770
|
negativePrompt: data.negative_prompt ?? "",
|
|
657
771
|
width,
|
|
658
|
-
height
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
if (data.seed !== void 0 || data.steps !== void 0 || data.cfg_scale !== void 0 || data.scheduler !== void 0) {
|
|
667
|
-
metadata.sampling = {
|
|
772
|
+
height,
|
|
773
|
+
model: trimObject({
|
|
774
|
+
name: data.model?.name,
|
|
775
|
+
hash: data.model?.hash
|
|
776
|
+
}),
|
|
777
|
+
sampling: trimObject({
|
|
668
778
|
seed: data.seed,
|
|
669
779
|
steps: data.steps,
|
|
670
780
|
cfg: data.cfg_scale,
|
|
671
781
|
sampler: data.scheduler
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
return Result.ok(metadata);
|
|
782
|
+
})
|
|
783
|
+
});
|
|
675
784
|
}
|
|
676
785
|
|
|
677
786
|
// src/parsers/novelai.ts
|
|
@@ -699,35 +808,31 @@ function parseNovelAI(entries) {
|
|
|
699
808
|
const height = comment.height ?? 0;
|
|
700
809
|
const prompt = comment.v4_prompt?.caption?.base_caption ?? comment.prompt ?? "";
|
|
701
810
|
const negativePrompt = comment.v4_negative_prompt?.caption?.base_caption ?? comment.uc ?? "";
|
|
702
|
-
const
|
|
811
|
+
const charCaptions = comment.v4_prompt?.caption?.char_captions;
|
|
812
|
+
const characterPrompts = charCaptions && charCaptions.length > 0 ? charCaptions.map((cc) => {
|
|
813
|
+
if (!cc.char_caption) return null;
|
|
814
|
+
return {
|
|
815
|
+
prompt: cc.char_caption,
|
|
816
|
+
center: cc.centers?.[0]
|
|
817
|
+
};
|
|
818
|
+
}).filter((cp) => cp !== null) : void 0;
|
|
819
|
+
return Result.ok({
|
|
703
820
|
software: "novelai",
|
|
704
821
|
prompt,
|
|
705
822
|
negativePrompt,
|
|
706
823
|
width,
|
|
707
|
-
height
|
|
708
|
-
|
|
709
|
-
if (comment.steps !== void 0 || comment.scale !== void 0 || comment.seed !== void 0 || comment.noise_schedule !== void 0 || comment.sampler !== void 0) {
|
|
710
|
-
metadata.sampling = {
|
|
824
|
+
height,
|
|
825
|
+
sampling: trimObject({
|
|
711
826
|
steps: comment.steps,
|
|
712
827
|
cfg: comment.scale,
|
|
713
828
|
seed: comment.seed,
|
|
714
829
|
sampler: comment.sampler,
|
|
715
830
|
scheduler: comment.noise_schedule
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
if (!cc.char_caption) return null;
|
|
722
|
-
return {
|
|
723
|
-
prompt: cc.char_caption,
|
|
724
|
-
center: cc.centers?.[0]
|
|
725
|
-
};
|
|
726
|
-
}).filter((cp) => cp !== null);
|
|
727
|
-
metadata.useCoords = comment.v4_prompt?.use_coords;
|
|
728
|
-
metadata.useOrder = comment.v4_prompt?.use_order;
|
|
729
|
-
}
|
|
730
|
-
return Result.ok(metadata);
|
|
831
|
+
}),
|
|
832
|
+
characterPrompts,
|
|
833
|
+
useCoords: characterPrompts ? comment.v4_prompt?.use_coords : void 0,
|
|
834
|
+
useOrder: characterPrompts ? comment.v4_prompt?.use_order : void 0
|
|
835
|
+
});
|
|
731
836
|
}
|
|
732
837
|
|
|
733
838
|
// src/parsers/ruined-fooocus.ts
|
|
@@ -777,43 +882,18 @@ function parseStabilityMatrix(entries) {
|
|
|
777
882
|
if (!comfyResult.ok || comfyResult.value.software !== "comfyui") {
|
|
778
883
|
return Result.error({ type: "unsupportedFormat" });
|
|
779
884
|
}
|
|
780
|
-
const
|
|
885
|
+
const jsonText = entryRecord["parameters-json"] ?? extractFromCommentJson(entryRecord, "parameters-json");
|
|
886
|
+
const parsed = jsonText ? parseJson(jsonText) : void 0;
|
|
887
|
+
const data = parsed?.ok ? parsed.value : void 0;
|
|
888
|
+
return Result.ok({
|
|
781
889
|
...comfyResult.value,
|
|
782
|
-
software: "stability-matrix"
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
if (commentParsed.ok) {
|
|
790
|
-
const commentData = commentParsed.value;
|
|
791
|
-
if (typeof commentData["parameters-json"] === "string") {
|
|
792
|
-
jsonText = commentData["parameters-json"];
|
|
793
|
-
} else if (typeof commentData["parameters-json"] === "object") {
|
|
794
|
-
jsonText = JSON.stringify(commentData["parameters-json"]);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
if (jsonText) {
|
|
799
|
-
const parsed = parseJson(jsonText);
|
|
800
|
-
if (parsed.ok) {
|
|
801
|
-
const data = parsed.value;
|
|
802
|
-
if (data.PositivePrompt !== void 0) {
|
|
803
|
-
metadata.prompt = data.PositivePrompt;
|
|
804
|
-
}
|
|
805
|
-
if (data.NegativePrompt !== void 0) {
|
|
806
|
-
metadata.negativePrompt = data.NegativePrompt;
|
|
807
|
-
}
|
|
808
|
-
if (data.ModelName !== void 0 || data.ModelHash !== void 0) {
|
|
809
|
-
metadata.model = {
|
|
810
|
-
name: data.ModelName,
|
|
811
|
-
hash: data.ModelHash
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
return Result.ok(metadata);
|
|
890
|
+
software: "stability-matrix",
|
|
891
|
+
// Override prompts from parameters-json (more complete than workflow)
|
|
892
|
+
prompt: data?.PositivePrompt ?? comfyResult.value.prompt,
|
|
893
|
+
negativePrompt: data?.NegativePrompt ?? comfyResult.value.negativePrompt,
|
|
894
|
+
// Override model if either name or hash is provided
|
|
895
|
+
model: data?.ModelName !== void 0 || data?.ModelHash !== void 0 ? { name: data?.ModelName, hash: data?.ModelHash } : comfyResult.value.model
|
|
896
|
+
});
|
|
817
897
|
}
|
|
818
898
|
|
|
819
899
|
// src/parsers/swarmui.ts
|
|
@@ -852,67 +932,37 @@ function parseSwarmUI(entries) {
|
|
|
852
932
|
}
|
|
853
933
|
const width = params.width ?? 0;
|
|
854
934
|
const height = params.height ?? 0;
|
|
855
|
-
const
|
|
935
|
+
const promptSource = entryRecord.prompt || entryRecord.Make;
|
|
936
|
+
const promptParsed = promptSource ? parseJson(promptSource) : void 0;
|
|
937
|
+
const nodes = promptParsed?.ok ? promptParsed.value : void 0;
|
|
938
|
+
return Result.ok({
|
|
856
939
|
software: "swarmui",
|
|
857
940
|
prompt: params.prompt ?? "",
|
|
858
941
|
negativePrompt: params.negativeprompt ?? "",
|
|
859
942
|
width,
|
|
860
|
-
height
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const promptParsed = parseJson(promptSource);
|
|
865
|
-
if (promptParsed.ok) {
|
|
866
|
-
metadata.nodes = promptParsed.value;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
if (params.model) {
|
|
870
|
-
metadata.model = {
|
|
871
|
-
name: params.model
|
|
872
|
-
};
|
|
873
|
-
}
|
|
874
|
-
if (params.seed !== void 0 || params.steps !== void 0 || params.cfgscale !== void 0 || params.sampler !== void 0 || params.scheduler !== void 0) {
|
|
875
|
-
metadata.sampling = {
|
|
943
|
+
height,
|
|
944
|
+
nodes,
|
|
945
|
+
model: trimObject({ name: params.model }),
|
|
946
|
+
sampling: trimObject({
|
|
876
947
|
seed: params.seed,
|
|
877
948
|
steps: params.steps,
|
|
878
949
|
cfg: params.cfgscale,
|
|
879
950
|
sampler: params.sampler,
|
|
880
951
|
scheduler: params.scheduler
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
if (params.refinerupscale !== void 0 || params.refinerupscalemethod !== void 0 || params.refinercontrolpercentage !== void 0) {
|
|
884
|
-
metadata.hires = {
|
|
952
|
+
}),
|
|
953
|
+
hires: trimObject({
|
|
885
954
|
scale: params.refinerupscale,
|
|
886
955
|
upscaler: params.refinerupscalemethod,
|
|
887
956
|
denoise: params.refinercontrolpercentage
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
return Result.ok(metadata);
|
|
957
|
+
})
|
|
958
|
+
});
|
|
891
959
|
}
|
|
892
960
|
|
|
893
961
|
// src/parsers/tensorart.ts
|
|
894
962
|
function parseTensorArt(entries) {
|
|
895
963
|
const entryRecord = buildEntryRecord(entries);
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
if (!dataText && entryRecord.Comment?.startsWith("{")) {
|
|
899
|
-
const commentParsed = parseJson(
|
|
900
|
-
entryRecord.Comment
|
|
901
|
-
);
|
|
902
|
-
if (commentParsed.ok) {
|
|
903
|
-
const commentData = commentParsed.value;
|
|
904
|
-
if (typeof commentData.generation_data === "string") {
|
|
905
|
-
dataText = commentData.generation_data;
|
|
906
|
-
} else if (typeof commentData.generation_data === "object") {
|
|
907
|
-
dataText = JSON.stringify(commentData.generation_data);
|
|
908
|
-
}
|
|
909
|
-
if (typeof commentData.prompt === "string") {
|
|
910
|
-
promptChunk = commentData.prompt;
|
|
911
|
-
} else if (typeof commentData.prompt === "object") {
|
|
912
|
-
promptChunk = JSON.stringify(commentData.prompt);
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
964
|
+
const dataText = entryRecord.generation_data ?? extractFromCommentJson(entryRecord, "generation_data");
|
|
965
|
+
const promptChunk = entryRecord.prompt ?? extractFromCommentJson(entryRecord, "prompt");
|
|
916
966
|
if (!dataText) {
|
|
917
967
|
return Result.error({ type: "unsupportedFormat" });
|
|
918
968
|
}
|
|
@@ -937,30 +987,26 @@ function parseTensorArt(entries) {
|
|
|
937
987
|
message: "Invalid JSON in prompt chunk"
|
|
938
988
|
});
|
|
939
989
|
}
|
|
940
|
-
const
|
|
990
|
+
const baseSeed = data.seed ? Number(data.seed) : void 0;
|
|
991
|
+
const seed = baseSeed === -1 ? findActualSeed(promptParsed.value) : baseSeed;
|
|
992
|
+
return Result.ok({
|
|
941
993
|
software: "tensorart",
|
|
942
994
|
prompt: data.prompt ?? "",
|
|
943
995
|
negativePrompt: data.negativePrompt ?? "",
|
|
944
996
|
width,
|
|
945
997
|
height,
|
|
946
|
-
nodes: promptParsed.value
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
}
|
|
954
|
-
if (data.seed !== void 0 || data.steps !== void 0 || data.cfgScale !== void 0 || data.clipSkip !== void 0) {
|
|
955
|
-
const baseSeed = data.seed ? Number(data.seed) : void 0;
|
|
956
|
-
metadata.sampling = {
|
|
957
|
-
seed: baseSeed === -1 ? findActualSeed(promptParsed.value) : baseSeed,
|
|
998
|
+
nodes: promptParsed.value,
|
|
999
|
+
model: trimObject({
|
|
1000
|
+
name: data.baseModel?.modelFileName,
|
|
1001
|
+
hash: data.baseModel?.hash
|
|
1002
|
+
}),
|
|
1003
|
+
sampling: trimObject({
|
|
1004
|
+
seed,
|
|
958
1005
|
steps: data.steps,
|
|
959
1006
|
cfg: data.cfgScale,
|
|
960
1007
|
clipSkip: data.clipSkip
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
return Result.ok(metadata);
|
|
1008
|
+
})
|
|
1009
|
+
});
|
|
964
1010
|
}
|
|
965
1011
|
function findActualSeed(nodes) {
|
|
966
1012
|
const samplerNode = findSamplerNode(nodes);
|
|
@@ -987,8 +1033,16 @@ function parseMetadata(entries) {
|
|
|
987
1033
|
return parseHfSpace(entries);
|
|
988
1034
|
case "civitai": {
|
|
989
1035
|
const comfyResult = parseComfyUI(entries);
|
|
990
|
-
if (comfyResult.ok)
|
|
991
|
-
|
|
1036
|
+
if (comfyResult.ok) {
|
|
1037
|
+
comfyResult.value.software = "civitai";
|
|
1038
|
+
return comfyResult;
|
|
1039
|
+
}
|
|
1040
|
+
const a1111Result = parseA1111(entries);
|
|
1041
|
+
if (a1111Result.ok) {
|
|
1042
|
+
a1111Result.value.software = "civitai";
|
|
1043
|
+
return a1111Result;
|
|
1044
|
+
}
|
|
1045
|
+
return a1111Result;
|
|
992
1046
|
}
|
|
993
1047
|
case "comfyui": {
|
|
994
1048
|
const comfyResult = parseComfyUI(entries);
|
|
@@ -1644,7 +1698,7 @@ function sourceToKeyword(source) {
|
|
|
1644
1698
|
}
|
|
1645
1699
|
|
|
1646
1700
|
// src/api/read.ts
|
|
1647
|
-
function read(input) {
|
|
1701
|
+
function read(input, options) {
|
|
1648
1702
|
const data = toUint8Array(input);
|
|
1649
1703
|
const format = detectFormat(data);
|
|
1650
1704
|
if (!format) {
|
|
@@ -1661,7 +1715,7 @@ function read(input) {
|
|
|
1661
1715
|
return { status: "unrecognized", raw };
|
|
1662
1716
|
}
|
|
1663
1717
|
const metadata = parseResult.value;
|
|
1664
|
-
if (metadata.width === 0 || metadata.height === 0) {
|
|
1718
|
+
if (!options?.strict && (metadata.width === 0 || metadata.height === 0)) {
|
|
1665
1719
|
const dims = HELPERS[format].readDimensions(data);
|
|
1666
1720
|
if (dims) {
|
|
1667
1721
|
metadata.width = metadata.width || dims.width;
|
|
@@ -1852,6 +1906,43 @@ function convertA1111SegmentsToPng(segments) {
|
|
|
1852
1906
|
return createEncodedChunk("parameters", userComment.data, "dynamic");
|
|
1853
1907
|
}
|
|
1854
1908
|
|
|
1909
|
+
// src/converters/civitai.ts
|
|
1910
|
+
function convertCivitaiPngToSegments(chunks) {
|
|
1911
|
+
const parametersChunk = chunks.find((c) => c.keyword === "parameters");
|
|
1912
|
+
if (parametersChunk && !parametersChunk.text.trimStart().startsWith("{")) {
|
|
1913
|
+
return convertA1111PngToSegments(chunks);
|
|
1914
|
+
}
|
|
1915
|
+
const data = {};
|
|
1916
|
+
for (const chunk of chunks) {
|
|
1917
|
+
if (chunk.keyword === "prompt") {
|
|
1918
|
+
const parsed = parseJson(chunk.text);
|
|
1919
|
+
if (parsed.ok && typeof parsed.value === "object" && parsed.value) {
|
|
1920
|
+
Object.assign(data, parsed.value);
|
|
1921
|
+
}
|
|
1922
|
+
} else if (chunk.keyword === "extraMetadata") {
|
|
1923
|
+
data[chunk.keyword] = chunk.text;
|
|
1924
|
+
} else {
|
|
1925
|
+
const parsed = parseJson(chunk.text);
|
|
1926
|
+
data[chunk.keyword] = parsed.ok ? parsed.value : chunk.text;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
return [
|
|
1930
|
+
{
|
|
1931
|
+
source: { type: "exifUserComment" },
|
|
1932
|
+
data: JSON.stringify(data)
|
|
1933
|
+
}
|
|
1934
|
+
];
|
|
1935
|
+
}
|
|
1936
|
+
function convertCivitaiSegmentsToPng(segments) {
|
|
1937
|
+
const userComment = findSegment(segments, "exifUserComment");
|
|
1938
|
+
if (!userComment) return [];
|
|
1939
|
+
const isJson = userComment.data.trimStart().startsWith("{");
|
|
1940
|
+
if (!isJson) {
|
|
1941
|
+
return convertA1111SegmentsToPng(segments);
|
|
1942
|
+
}
|
|
1943
|
+
return createEncodedChunk("prompt", userComment.data, "text-utf8-raw");
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1855
1946
|
// src/converters/base-json.ts
|
|
1856
1947
|
function convertKvPngToSegments(chunks) {
|
|
1857
1948
|
const data = {};
|
|
@@ -2101,7 +2192,7 @@ function convertMetadata(parseResult, targetFormat) {
|
|
|
2101
2192
|
});
|
|
2102
2193
|
}
|
|
2103
2194
|
const raw = parseResult.raw;
|
|
2104
|
-
if (raw.format ===
|
|
2195
|
+
if (raw.format === targetFormat) {
|
|
2105
2196
|
return Result.ok(raw);
|
|
2106
2197
|
}
|
|
2107
2198
|
const software = parseResult.metadata.software;
|
|
@@ -2166,15 +2257,20 @@ var convertHfSpace = createFormatConverter(
|
|
|
2166
2257
|
createPngToSegments("parameters"),
|
|
2167
2258
|
createSegmentsToPng("parameters", "text-unicode-escape")
|
|
2168
2259
|
);
|
|
2260
|
+
var convertCivitai = createFormatConverter(
|
|
2261
|
+
convertCivitaiPngToSegments,
|
|
2262
|
+
convertCivitaiSegmentsToPng
|
|
2263
|
+
);
|
|
2169
2264
|
var softwareConverters = {
|
|
2170
2265
|
// NovelAI
|
|
2171
2266
|
novelai: convertNovelai,
|
|
2172
|
-
// A1111-format (sd-webui, forge, forge-neo,
|
|
2267
|
+
// A1111-format (sd-webui, forge, forge-neo, sd-next)
|
|
2173
2268
|
"sd-webui": convertA1111,
|
|
2174
2269
|
"sd-next": convertA1111,
|
|
2175
2270
|
forge: convertA1111,
|
|
2176
2271
|
"forge-neo": convertA1111,
|
|
2177
|
-
|
|
2272
|
+
// CivitAI Orchestration format
|
|
2273
|
+
civitai: convertCivitai,
|
|
2178
2274
|
// ComfyUI-format (comfyui, tensorart, stability-matrix)
|
|
2179
2275
|
comfyui: convertComfyUI,
|
|
2180
2276
|
tensorart: convertComfyUI,
|