@enslo/sd-metadata 1.0.2 → 1.1.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.md CHANGED
@@ -13,7 +13,7 @@ A TypeScript library to read and write metadata embedded in AI-generated images.
13
13
  - **TypeScript Native**: Written in TypeScript with full type definitions included
14
14
  - **Zero Dependencies**: Works in Node.js and browsers without any external dependencies
15
15
  - **Format Conversion**: Seamlessly convert metadata between PNG, JPEG, and WebP
16
- - **Lossless Round-trip**: Preserves original metadata structure when converting back to native format
16
+ - **Metadata Preservation**: Preserves original metadata structure when converting formats (e.g., PNG → JPEG → PNG maintains all original data)
17
17
 
18
18
  ## Installation
19
19
 
@@ -42,15 +42,47 @@ npm install @enslo/sd-metadata
42
42
  **Legend:**
43
43
 
44
44
  - ✅ **Fully Supported** - Formats natively supported by the tool, verified with sample files
45
- - 🔄️ **Extended Support** - sd-metadata specific parsers, cross-format conversion supported
46
- - ⚠️ **Experimental** - Implemented from reference code, not verified with samples
45
+ - 🔄️ **Extended Support** - Formats not natively supported by the tool, but sd-metadata enables read/write through custom format conversion. Supports round-trip conversion back to native formats.
46
+ - ⚠️ **Experimental** - Implemented by analyzing reference code or documentation, not verified with actual sample files. May not extract all metadata fields correctly.
47
+
48
+ **Extended Support Examples:**
49
+
50
+ - **Stability Matrix** (native: PNG only) → sd-metadata enables JPEG/WebP support
51
+ - **NovelAI** (native: PNG, WebP) → sd-metadata enables JPEG support
52
+
53
+ When you convert from a native format to an extended format and back (e.g., PNG → JPEG → PNG), all metadata is preserved.
47
54
 
48
55
  > [!NOTE]
49
- > \* Tools with known limitations. See [Known Limitations](#known-limitations) for details.
56
+ > \* Tools with format-specific behaviors. See [Format-Specific Behaviors](#format-specific-behaviors) for details.
50
57
 
51
58
  > [!TIP]
52
59
  > **Help us expand tool support!** We're actively collecting sample images from experimental tools (Easy Diffusion, Fooocus) and unsupported tools. If you have sample images generated by these or other AI tools, please consider contributing them! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
53
60
 
61
+ ## Format-Specific Behaviors
62
+
63
+ Some tools have specific behaviors when converting between formats:
64
+
65
+ - **ComfyUI JPEG/WebP**: Reading supports multiple custom node formats (e.g., `save-image-extended`), but writing always uses the `comfyui-saveimage-plus` format for best information preservation and compatibility with ComfyUI's native drag-and-drop workflow loading.
66
+ - **NovelAI WebP**: Automatically corrects corrupted UTF-8 in the Description field. WebP → PNG → WebP round-trip produces valid, readable metadata but with minor text corrections.
67
+ - **SwarmUI PNG→JPEG/WebP**: Native SwarmUI JPEG/WebP files do not include node information. When converting from PNG, this library preserves the ComfyUI workflow in the `Make` field for complete metadata retention (extended support).
68
+
69
+ ## Import
70
+
71
+ **ESM (TypeScript / Modern JavaScript):**
72
+
73
+ ```typescript
74
+ import { read } from '@enslo/sd-metadata';
75
+ ```
76
+
77
+ **CommonJS (Node.js):**
78
+
79
+ ```javascript
80
+ const { read } = require('@enslo/sd-metadata');
81
+ ```
82
+
83
+ > [!NOTE]
84
+ > All examples below use ESM syntax. CommonJS users can replace `import` with `require`.
85
+
54
86
  ## Usage
55
87
 
56
88
  ### Node.js Usage
@@ -64,10 +96,10 @@ const imageData = readFileSync('image.png');
64
96
  const result = read(imageData);
65
97
 
66
98
  if (result.status === 'success') {
67
- console.log('Tool:', result.tool); // 'novelai', 'comfyui', etc.
68
- console.log('Prompt:', result.prompt);
69
- console.log('Model:', result.parameters?.model);
70
- console.log('Size:', result.width, 'x', result.height);
99
+ console.log('Tool:', result.metadata.software); // 'novelai', 'comfyui', etc.
100
+ console.log('Prompt:', result.metadata.prompt);
101
+ console.log('Model:', result.metadata.model?.name);
102
+ console.log('Size:', result.metadata.width, 'x', result.metadata.height);
71
103
  }
72
104
  ```
73
105
 
@@ -80,19 +112,48 @@ import { read } from 'sd-metadata';
80
112
  const fileInput = document.querySelector('input[type="file"]');
81
113
  fileInput.addEventListener('change', async (e) => {
82
114
  const file = e.target.files[0];
115
+ if (!file) return;
116
+
83
117
  const arrayBuffer = await file.arrayBuffer();
84
118
  const imageData = new Uint8Array(arrayBuffer);
85
119
 
86
120
  const result = read(imageData);
87
121
 
88
122
  if (result.status === 'success') {
89
- document.getElementById('tool').textContent = result.tool;
90
- document.getElementById('prompt').textContent = result.prompt;
91
- document.getElementById('model').textContent = result.parameters?.model || 'N/A';
123
+ document.getElementById('tool').textContent = result.metadata.software;
124
+ document.getElementById('prompt').textContent = result.metadata.prompt;
125
+ document.getElementById('model').textContent = result.metadata.model?.name || 'N/A';
92
126
  }
93
127
  });
94
128
  ```
95
129
 
130
+ ### CDN Usage (Bookmarklet / Userscript)
131
+
132
+ For bookmarklets or userscripts (Tampermonkey, Violentmonkey, etc.), load from jsDelivr CDN:
133
+
134
+ ```javascript
135
+ // Import from CDN
136
+ import { read } from 'https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@latest/dist/index.js';
137
+
138
+ // Fetch image and read metadata
139
+ const response = await fetch(imageUrl);
140
+ const arrayBuffer = await response.arrayBuffer();
141
+ const imageData = new Uint8Array(arrayBuffer);
142
+
143
+ const result = read(imageData);
144
+ if (result.status === 'success') {
145
+ console.log('Tool:', result.metadata.software);
146
+ console.log('Prompt:', result.metadata.prompt);
147
+ }
148
+ ```
149
+
150
+ > [!TIP]
151
+ > For production use, pin to a specific version instead of `@latest`:
152
+ >
153
+ > ```text
154
+ > https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@1.1.1/dist/index.js
155
+ > ```
156
+
96
157
  ### Format Conversion
97
158
 
98
159
  Convert metadata between different image formats:
@@ -100,20 +161,27 @@ Convert metadata between different image formats:
100
161
  ```typescript
101
162
  import { read, write } from 'sd-metadata';
102
163
 
103
- // Read from PNG
164
+ // Read metadata from PNG
104
165
  const pngData = readFileSync('comfyui-output.png');
105
- const metadata = read(pngData);
106
-
107
- // Write to JPEG
108
- const jpegData = readFileSync('target.jpg');
109
- const result = write(jpegData, metadata);
166
+ const parseResult = read(pngData);
110
167
 
111
- if (result.type === 'success') {
112
- writeFileSync('output.jpg', result.data);
113
- console.log('Metadata converted from PNG to JPEG');
168
+ if (parseResult.status === 'success') {
169
+ // Convert PNG to JPEG (using your preferred image processing library)
170
+ const jpegImageData = convertToJpeg(pngData); // Pseudo-code: use sharp, canvas, etc.
171
+
172
+ // Embed the metadata into the JPEG
173
+ const result = write(jpegImageData, parseResult);
174
+
175
+ if (result.ok) {
176
+ writeFileSync('output.jpg', result.value);
177
+ console.log('Image converted to JPEG with metadata preserved');
178
+ }
114
179
  }
115
180
  ```
116
181
 
182
+ > [!TIP]
183
+ > This library handles metadata read/write only. For actual image format conversion (decoding/encoding pixels), use image processing libraries like [sharp](https://www.npmjs.com/package/sharp), [jimp](https://www.npmjs.com/package/jimp), or browser Canvas API.
184
+
117
185
  ### Handling Different Result Types
118
186
 
119
187
  ```typescript
@@ -124,13 +192,13 @@ const result = read(imageData);
124
192
  switch (result.status) {
125
193
  case 'success':
126
194
  // Metadata successfully parsed
127
- console.log(`Generated by ${result.tool}`);
128
- console.log(`Prompt: ${result.prompt}`);
195
+ console.log(`Generated by ${result.metadata.software}`);
196
+ console.log(`Prompt: ${result.metadata.prompt}`);
129
197
  break;
130
198
 
131
199
  case 'unrecognized':
132
- // Format detected but not recognized as AI-generated
133
- console.log('Not an AI-generated image');
200
+ // Metadata exists but format is not recognized
201
+ console.log('Unknown metadata format');
134
202
  // You can still access raw metadata for debugging:
135
203
  console.log('Raw chunks:', result.raw);
136
204
  break;
@@ -140,11 +208,6 @@ switch (result.status) {
140
208
  console.log('No metadata in this image');
141
209
  break;
142
210
 
143
- case 'unsupportedFormat':
144
- // Not a PNG, JPEG, or WebP file
145
- console.log('Unsupported image format');
146
- break;
147
-
148
211
  case 'invalid':
149
212
  // Corrupted or invalid image data
150
213
  console.log('Error:', result.message);
@@ -165,7 +228,7 @@ const source = read(unknownImage);
165
228
  // Force blind conversion (preserves all metadata chunks/segments)
166
229
  const result = write(targetImage, source, { force: true });
167
230
 
168
- if (result.type === 'success') {
231
+ if (result.ok) {
169
232
  // Metadata successfully converted even though format wasn't recognized
170
233
  console.log('Forced conversion succeeded');
171
234
  }
@@ -179,8 +242,8 @@ To strip all metadata from an image:
179
242
  import { write } from 'sd-metadata';
180
243
 
181
244
  const result = write(imageData, { status: 'empty' });
182
- if (result.type === 'success') {
183
- writeFileSync('clean-image.png', result.data);
245
+ if (result.ok) {
246
+ writeFileSync('clean-image.png', result.value);
184
247
  }
185
248
  ```
186
249
 
@@ -192,11 +255,14 @@ Reads and parses metadata from an image file.
192
255
 
193
256
  **Returns:**
194
257
 
195
- - `{ status: 'success', tool, prompt, parameters, width, height, raw }` - Successfully parsed
258
+ - `{ status: 'success', metadata, raw }` - Successfully parsed
259
+ - `metadata`: Unified metadata object (see `GenerationMetadata`)
260
+ - `raw`: Original format-specific data (chunks/segments)
196
261
  - `{ status: 'unrecognized', raw }` - Image has metadata but not from a known AI tool
197
- - `{ status: 'empty' }` - No metadata found
198
- - `{ status: 'unsupportedFormat' }` - Not a PNG, JPEG, or WebP file
199
- - `{ status: 'invalid', message }` - Corrupted or invalid image data
262
+ - `raw`: Original metadata preserved for conversion
263
+ - `{ status: 'empty' }` - No metadata found in the image
264
+ - `{ status: 'invalid', message? }` - Corrupted or unsupported image format
265
+ - `message`: Optional error description
200
266
 
201
267
  ### `write(data: Uint8Array, metadata: ParseResult, options?: WriteOptions): WriteResult`
202
268
 
@@ -205,29 +271,137 @@ Writes metadata to an image file.
205
271
  **Parameters:**
206
272
 
207
273
  - `data` - Target image file data (PNG, JPEG, or WebP)
208
- - `metadata` - ParseResult from `read()`
274
+ - `metadata` - `ParseResult` from `read()`
209
275
  - `status: 'success'` or `'empty'` - Can write directly
210
276
  - `status: 'unrecognized'` - Requires `force: true` option
211
277
  - `options` - Optional settings:
212
- - `force?: boolean` - Required when writing `status: 'unrecognized'` metadata
278
+ - `force?: boolean` - Required when writing `status: 'unrecognized'` metadata (blind conversion)
213
279
 
214
280
  **Returns:**
215
281
 
216
- - `{ type: 'success', data }` - Successfully written
217
- - `{ type: 'unsupportedFormat' }` - Target is not PNG, JPEG, or WebP
218
- - `{ type: 'conversionFailed', message }` - Metadata conversion failed
219
- - `{ type: 'writeFailed', message }` - Failed to write metadata to image
282
+ - `{ ok: true, value: Uint8Array }` - Successfully written (returns new image data)
283
+ - `{ ok: false, error: { type: string, message?: string } }` - Failed
284
+ - `type`: `'unsupportedFormat'`, `'conversionFailed'`, or `'writeFailed'`
220
285
 
221
- ## Known Limitations
286
+ ## Type Reference
222
287
 
223
- > [!WARNING]
224
- > **ComfyUI JPEG/WebP**: While reading supports major custom node formats (e.g., `save-image-extended`), writing always uses the `comfyui-saveimage-plus` format. This format provides the best information preservation and is compatible with ComfyUI's native drag-and-drop workflow loading.
288
+ This section provides an overview of the main types. For complete type definitions, see [Type Documentation](./docs/types.md).
225
289
 
226
- > [!WARNING]
227
- > **NovelAI WebP**: Auto-corrects corrupted UTF-8 in the Description field, which means WebP → PNG → WebP round-trip is not content-equivalent (but provides valid, readable metadata).
290
+ ### `ParseResult`
228
291
 
229
- > [!WARNING]
230
- > **SwarmUI PNG→JPEG/WebP**: PNG files contain both ComfyUI workflow and SwarmUI parameters. When converting to JPEG/WebP, only parameters are preserved to match the native format. Metadata is fully preserved, but the ComfyUI workflow in the `prompt` chunk is lost.
292
+ The result of the `read()` function. It uses a discriminated union with a `status` field.
293
+
294
+ ```typescript
295
+ type ParseResult =
296
+ | { status: 'success'; metadata: GenerationMetadata; raw: RawMetadata }
297
+ | { status: 'unrecognized'; raw: RawMetadata }
298
+ | { status: 'empty' }
299
+ | { status: 'invalid'; message?: string };
300
+ ```
301
+
302
+ ### `GenerationMetadata`
303
+
304
+ Unified metadata structure returned by the `read()` function. This is a discriminated union of 3 specific metadata types, distinguished by the `software` field.
305
+
306
+ **Common Fields (Available in All Types):**
307
+
308
+ All metadata types include these base fields:
309
+
310
+ - `prompt: string` - Positive prompt text
311
+ - `negativePrompt: string` - Negative prompt text
312
+ - `width: number` - Image width in pixels
313
+ - `height: number` - Image height in pixels
314
+ - `model?: ModelSettings` - Model information (name, hash, VAE)
315
+ - `sampling?: SamplingSettings` - Sampling parameters (seed, steps, CFG, sampler, scheduler, clipSkip)
316
+ - `hires?: HiresSettings` - Hires.fix settings (if applied)
317
+ - `upscale?: UpscaleSettings` - Upscale settings (if applied)
318
+
319
+ **Metadata Type Variants:**
320
+
321
+ - **`NovelAIMetadata`** (`software: 'novelai'`)
322
+ Includes NovelAI-specific fields for V4 character placement:
323
+ - `characterPrompts?: CharacterPrompt[]` - Per-character prompts with positions
324
+ - `useCoords?: boolean` - Use character coordinates for placement
325
+ - `useOrder?: boolean` - Use character order
326
+
327
+ - **`ComfyUIMetadata`** (`software: 'comfyui' | 'tensorart' | 'stability-matrix' | 'swarmui'`)
328
+ Includes ComfyUI workflow graph:
329
+ - `nodes: ComfyNodeGraph` (required for comfyui/tensorart/stability-matrix)
330
+ - `nodes?: ComfyNodeGraph` (optional for swarmui - only in PNG format)
331
+
332
+ - **`StandardMetadata`** (`software: 'sd-webui' | 'forge' | 'invokeai' | 'civitai' | ...`)
333
+ Baseline metadata without tool-specific extensions. Used by most SD WebUI-based tools.
334
+
335
+ **Type Definition:**
336
+
337
+ ```typescript
338
+ type GenerationMetadata =
339
+ | NovelAIMetadata
340
+ | ComfyUIMetadata
341
+ | StandardMetadata;
342
+ ```
343
+
344
+ **Usage Example:**
345
+
346
+ ```typescript
347
+ const result = read(imageData);
348
+
349
+ if (result.status === 'success') {
350
+ const metadata = result.metadata;
351
+
352
+ // Access common fields
353
+ console.log('Prompt:', metadata.prompt);
354
+ console.log('Model:', metadata.model?.name);
355
+ console.log('Seed:', metadata.sampling?.seed);
356
+
357
+ // Type-specific handling using discriminated union
358
+ if (metadata.software === 'novelai') {
359
+ // TypeScript knows this is NovelAIMetadata
360
+ console.log('Character prompts:', metadata.characterPrompts);
361
+ } else if (
362
+ metadata.software === 'comfyui' ||
363
+ metadata.software === 'tensorart' ||
364
+ metadata.software === 'stability-matrix'
365
+ ) {
366
+ // TypeScript knows this is BasicComfyUIMetadata (nodes always present)
367
+ console.log('Node count:', Object.keys(metadata.nodes).length);
368
+ } else if (metadata.software === 'swarmui') {
369
+ // TypeScript knows this is SwarmUIMetadata (nodes optional)
370
+ if (metadata.nodes) {
371
+ console.log('Workflow included');
372
+ }
373
+ }
374
+ }
375
+ ```
376
+
377
+ See [Type Documentation](./docs/types.md) for detailed interface definitions of each metadata type.
378
+
379
+ ### `RawMetadata`
380
+
381
+ Preserves the original metadata structure for round-trip conversions.
382
+
383
+ ```typescript
384
+ type RawMetadata =
385
+ | { format: 'png'; chunks: PngTextChunk[] }
386
+ | { format: 'jpeg'; segments: MetadataSegment[] }
387
+ | { format: 'webp'; segments: MetadataSegment[] };
388
+ ```
389
+
390
+ > [!TIP]
391
+ > For TypeScript users: All types are exported and available for import.
392
+ >
393
+ > ```typescript
394
+ > import type {
395
+ > ParseResult,
396
+ > GenerationMetadata,
397
+ > ModelSettings,
398
+ > SamplingSettings
399
+ > } from '@enslo/sd-metadata';
400
+ > ```
401
+ >
402
+ > Use your IDE's IntelliSense for auto-completion and inline documentation.
403
+
404
+ For detailed documentation of all exported types including `BaseMetadata`, `ModelSettings`, `SamplingSettings`, and format-specific types, see the [Type Documentation](./docs/types.md).
231
405
 
232
406
  ## Development
233
407
 
package/dist/index.d.ts CHANGED
@@ -84,23 +84,10 @@ interface ITXtChunk {
84
84
  /** Text content */
85
85
  text: string;
86
86
  }
87
- /**
88
- * Known AI image generation software
89
- */
90
- type GenerationSoftware = 'novelai' | 'comfyui' | 'swarmui' | 'tensorart' | 'stability-matrix' | 'invokeai' | 'forge-neo' | 'forge' | 'sd-webui' | 'sd-next' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus';
91
- /**
92
- * Metadata format classification
93
- *
94
- * This represents the format/structure of the metadata, not the specific tool.
95
- * Use this to determine which fields are available and how to interpret them.
96
- */
97
- type MetadataFormat = 'novelai' | 'comfyui' | 'a1111' | 'invokeai' | 'swarmui';
98
87
  /**
99
88
  * Base metadata fields shared by all tools
100
89
  */
101
90
  interface BaseMetadata {
102
- /** Format classification (for type narrowing) */
103
- type: MetadataFormat;
104
91
  /** Positive prompt */
105
92
  prompt: string;
106
93
  /** Negative prompt */
@@ -122,7 +109,6 @@ interface BaseMetadata {
122
109
  * NovelAI-specific metadata
123
110
  */
124
111
  interface NovelAIMetadata extends BaseMetadata {
125
- type: 'novelai';
126
112
  software: 'novelai';
127
113
  /** V4 character prompts (when using character placement) */
128
114
  characterPrompts?: CharacterPrompt[];
@@ -148,47 +134,104 @@ interface CharacterPrompt {
148
134
  *
149
135
  * These tools use ComfyUI-compatible workflow format.
150
136
  */
151
- interface ComfyUIMetadata extends BaseMetadata {
152
- type: 'comfyui';
153
- software: 'comfyui' | 'tensorart' | 'stability-matrix';
154
- /** Full workflow JSON (for reproducibility) */
155
- workflow?: unknown;
156
- }
157
137
  /**
158
- * A1111-format metadata (SD WebUI, Forge, Forge Neo, Civitai)
138
+ * ComfyUI node reference (for node outputs)
139
+ *
140
+ * Format: [nodeId, outputIndex]
141
+ * Example: ["CheckpointLoader_Base", 0]
159
142
  */
160
- interface A1111Metadata extends BaseMetadata {
161
- type: 'a1111';
162
- software: 'sd-webui' | 'sd-next' | 'forge' | 'forge-neo' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus';
143
+ type ComfyNodeReference = [nodeId: string, outputIndex: number];
144
+ /**
145
+ * ComfyUI node input value
146
+ */
147
+ type ComfyNodeInputValue = string | number | boolean | ComfyNodeReference | ComfyNodeInputValue[];
148
+ /**
149
+ * ComfyUI node structure
150
+ */
151
+ interface ComfyNode {
152
+ /** Node class type (e.g., "CheckpointLoaderSimple", "KSampler") */
153
+ class_type: string;
154
+ /** Node inputs */
155
+ inputs: Record<string, ComfyNodeInputValue>;
156
+ /** Node metadata (ComfyUI only) */
157
+ _meta?: {
158
+ /** Node title for display */
159
+ title?: string;
160
+ };
161
+ /** Change detection hash (rare, for caching) */
162
+ is_changed?: string[] | null;
163
163
  }
164
164
  /**
165
- * InvokeAI-specific metadata
165
+ * ComfyUI node graph
166
+ *
167
+ * Maps node IDs to their corresponding node data.
168
+ */
169
+ type ComfyNodeGraph = Record<string, ComfyNode>;
170
+ /**
171
+ * ComfyUI-format metadata (ComfyUI, TensorArt, Stability Matrix)
172
+ *
173
+ * These tools always have nodes in all formats.
166
174
  */
167
- interface InvokeAIMetadata extends BaseMetadata {
168
- type: 'invokeai';
169
- software: 'invokeai';
175
+ interface BasicComfyUIMetadata extends BaseMetadata {
176
+ software: 'comfyui' | 'tensorart' | 'stability-matrix';
177
+ /**
178
+ * ComfyUI node graph (required)
179
+ *
180
+ * Always present in all image formats (PNG, JPEG, WebP).
181
+ * Structure: Record<nodeId, ComfyNode> where ComfyNode contains inputs and class_type.
182
+ */
183
+ nodes: ComfyNodeGraph;
170
184
  }
171
185
  /**
172
186
  * SwarmUI-specific metadata
187
+ *
188
+ * SwarmUI uses ComfyUI workflow format but nodes are only present in PNG.
173
189
  */
174
190
  interface SwarmUIMetadata extends BaseMetadata {
175
- type: 'swarmui';
176
191
  software: 'swarmui';
192
+ /**
193
+ * ComfyUI node graph (optional for SwarmUI)
194
+ *
195
+ * Only present in PNG format. JPEG/WebP contain SwarmUI parameters only.
196
+ * Structure: Record<nodeId, ComfyNode> where ComfyNode contains inputs and class_type.
197
+ */
198
+ nodes?: ComfyNodeGraph;
199
+ }
200
+ /**
201
+ * ComfyUI-format metadata (union of BasicComfyUI and SwarmUI)
202
+ *
203
+ * This is a union type to handle different node graph requirements:
204
+ * - ComfyUI/TensorArt/Stability Matrix: nodes are always present
205
+ * - SwarmUI: nodes are only present in PNG format
206
+ */
207
+ type ComfyUIMetadata = BasicComfyUIMetadata | SwarmUIMetadata;
208
+ /**
209
+ * Standard metadata (SD WebUI, Forge, InvokeAI, and others)
210
+ *
211
+ * Baseline generation metadata without tool-specific extensions.
212
+ * Used by most SD tools that don't require special features like
213
+ * NovelAI's character prompts or ComfyUI's node graphs.
214
+ */
215
+ interface StandardMetadata extends BaseMetadata {
216
+ software: 'sd-webui' | 'sd-next' | 'forge' | 'forge-neo' | 'invokeai' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus';
177
217
  }
178
218
  /**
179
219
  * Unified generation metadata (discriminated union)
180
220
  *
181
- * Use `metadata.type` to narrow by format, or `metadata.software` for specific tool:
221
+ * Use `metadata.software` to narrow by specific tool:
182
222
  * ```typescript
183
- * if (metadata.type === 'comfyui') {
184
- * // TypeScript knows metadata.workflow exists
185
- * }
186
- * if (metadata.software === 'tensorart') {
187
- * // Specific tool within comfyui format
223
+ * if (metadata.software === 'comfyui' ||
224
+ * metadata.software === 'tensorart' ||
225
+ * metadata.software === 'stability-matrix' ||
226
+ * metadata.software === 'swarmui') {
227
+ * // TypeScript knows metadata is ComfyUIMetadata
228
+ * if (metadata.nodes) {
229
+ * // Access workflow graph
230
+ * }
188
231
  * }
189
232
  * ```
190
233
  */
191
- type GenerationMetadata = NovelAIMetadata | ComfyUIMetadata | A1111Metadata | InvokeAIMetadata | SwarmUIMetadata;
234
+ type GenerationMetadata = NovelAIMetadata | ComfyUIMetadata | StandardMetadata;
192
235
  /**
193
236
  * Model settings
194
237
  */
@@ -317,4 +360,4 @@ declare function read(data: Uint8Array): ParseResult;
317
360
  */
318
361
  declare function write(data: Uint8Array, metadata: ParseResult, options?: WriteOptions): WriteResult;
319
362
 
320
- export { type GenerationMetadata, type GenerationSoftware, type MetadataFormat, type ParseResult, type RawMetadata, type WriteOptions, type WriteResult, read, write };
363
+ export { type CharacterPrompt, type GenerationMetadata, type HiresSettings, type ITXtChunk, type MetadataSegment, type MetadataSegmentSource, type ModelSettings, type ParseResult, type PngTextChunk, type RawMetadata, type SamplingSettings, type TExtChunk, type UpscaleSettings, type WriteOptions, type WriteResult, read, write };