pixelkiln 0.66.0 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +811 -477
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +745 -443
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1105 -303
- package/dist/index.d.ts +1105 -303
- package/dist/index.js +743 -443
- package/dist/index.js.map +1 -1
- package/docs/CLI.md +17 -0
- package/docs/GENERATORS.md +31 -0
- package/docs/MANIFEST.md +7 -3
- package/docs/PIXELLAB.md +19 -15
- package/docs/REVISIONS.md +98 -10
- package/package.json +1 -1
- package/schema/manifest.schema.json +74 -0
- package/skills/pixelkiln/references/pixellab-roadmap.md +43 -17
- package/skills/pixelkiln/references/pixellab.md +42 -21
package/dist/index.cjs
CHANGED
|
@@ -82,6 +82,8 @@ __export(index_exports, {
|
|
|
82
82
|
ManifestEditSchema: () => ManifestEditSchema,
|
|
83
83
|
ManifestInputSchema: () => ManifestInputSchema,
|
|
84
84
|
ManifestSchema: () => ManifestSchema,
|
|
85
|
+
MapScenePlacementSchema: () => MapScenePlacementSchema,
|
|
86
|
+
MapSceneSchema: () => MapSceneSchema,
|
|
85
87
|
MediaType: () => MediaType,
|
|
86
88
|
OverwriteRefusedError: () => OverwriteRefusedError,
|
|
87
89
|
PIXEL_ART_FIXER_REVISION: () => PIXEL_ART_FIXER_REVISION,
|
|
@@ -332,6 +334,7 @@ var RevisionModeSchema = import_zod.z.enum([
|
|
|
332
334
|
"correct-pixelart",
|
|
333
335
|
"animate",
|
|
334
336
|
"animate-pixminimax",
|
|
337
|
+
"animate-skeleton",
|
|
335
338
|
"interpolate",
|
|
336
339
|
"edit-animation"
|
|
337
340
|
]);
|
|
@@ -520,6 +523,16 @@ var CharacterPortraitSchema = import_zod.z.object({
|
|
|
520
523
|
of: import_zod.z.string().min(1),
|
|
521
524
|
size: CharacterPortraitSizeSchema.default(64)
|
|
522
525
|
}).strict();
|
|
526
|
+
var MapScenePlacementSchema = import_zod.z.union([
|
|
527
|
+
import_zod.z.object({ oval: import_zod.z.number().min(0.05).max(0.95) }).strict(),
|
|
528
|
+
import_zod.z.object({ rectangle: import_zod.z.number().min(0.05).max(0.95) }).strict(),
|
|
529
|
+
import_zod.z.object({ mask: import_zod.z.string().min(1) }).strict()
|
|
530
|
+
]);
|
|
531
|
+
var MapSceneSchema = import_zod.z.object({
|
|
532
|
+
/** Manifest-relative PNG of the scene. Any earlier asset's output file works. */
|
|
533
|
+
image: import_zod.z.string().min(1),
|
|
534
|
+
placement: MapScenePlacementSchema.default({ oval: 0.3 })
|
|
535
|
+
}).strict();
|
|
523
536
|
var CharacterOutfitSchema = import_zod.z.object({
|
|
524
537
|
/** The loop (a character animation asset) to re-clothe, in the same style. */
|
|
525
538
|
of: import_zod.z.string().min(1),
|
|
@@ -650,6 +663,30 @@ var RevisionSchema = import_zod.z.object({
|
|
|
650
663
|
direction: CharacterDirectionSchema.optional(),
|
|
651
664
|
/** `animate`/`animate-pixminimax` only: let PixelLab expand the action into a fuller motion description first. */
|
|
652
665
|
enhancePrompt: import_zod.z.boolean().optional(),
|
|
666
|
+
/**
|
|
667
|
+
* `animate-skeleton` only: manifest-relative path to a committed
|
|
668
|
+
* `SkeletonSet` JSON file (see `src/skeleton.ts`) — the pose the parent
|
|
669
|
+
* image is already in, plus 3-15 per-frame poses for the motion.
|
|
670
|
+
* Authored via `pixelkiln estimate-skeleton`, then hand-tweaked; never
|
|
671
|
+
* inline in the manifest, the same reasoning `mask`/`lastFrame` are
|
|
672
|
+
* committed files rather than inline pixel data.
|
|
673
|
+
*/
|
|
674
|
+
keypointsFile: import_zod.z.string().min(1).optional(),
|
|
675
|
+
/**
|
|
676
|
+
* `animate-skeleton` only: the body a joint's missing `depth` is taken
|
|
677
|
+
* from. PixelLab's default is `mannequin`; free string like `character`'s
|
|
678
|
+
* own `template` field, validated at the provider layer against the
|
|
679
|
+
* same `mannequin`/`bear`/`cat`/`dog`/`horse`/`lion` vocabulary.
|
|
680
|
+
*/
|
|
681
|
+
skeletonTemplate: import_zod.z.string().min(1).optional(),
|
|
682
|
+
/**
|
|
683
|
+
* `animate-skeleton` only: what the character *looks like*, a noun
|
|
684
|
+
* phrase (colours, clothing, held items) — distinct from the asset's
|
|
685
|
+
* own `prompt`, which this mode sends as the motion's short label
|
|
686
|
+
* (PixelLab's `action`), the same `prompt`-as-motion convention
|
|
687
|
+
* `animate`/`animate-pixminimax` already use.
|
|
688
|
+
*/
|
|
689
|
+
description: import_zod.z.string().min(1).optional(),
|
|
653
690
|
/**
|
|
654
691
|
* `image-to-image`/`inpaint` only: which provider engine draws the
|
|
655
692
|
* edit. `pro-flash` selects PixelLab's Pro Flash edit and inpaint tier
|
|
@@ -740,18 +777,41 @@ var RevisionSchema = import_zod.z.object({
|
|
|
740
777
|
path: ["fps"]
|
|
741
778
|
});
|
|
742
779
|
}
|
|
743
|
-
if (revision.direction !== void 0 && revision.mode !== "animate-pixminimax") {
|
|
780
|
+
if (revision.direction !== void 0 && revision.mode !== "animate-pixminimax" && revision.mode !== "animate-skeleton") {
|
|
744
781
|
context.addIssue({
|
|
745
782
|
code: import_zod.z.ZodIssueCode.custom,
|
|
746
|
-
message: "direction applies to animate-pixminimax revisions only",
|
|
783
|
+
message: "direction applies to animate-pixminimax/animate-skeleton revisions only",
|
|
784
|
+
path: ["direction"]
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
if (revision.mode === "animate-skeleton" && revision.direction === void 0) {
|
|
788
|
+
context.addIssue({
|
|
789
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
790
|
+
message: "animate-skeleton revisions require a direction",
|
|
747
791
|
path: ["direction"]
|
|
748
792
|
});
|
|
749
793
|
}
|
|
750
794
|
if (revision.frames !== void 0 && revision.frames % 2 !== 0) {
|
|
751
795
|
context.addIssue({ code: import_zod.z.ZodIssueCode.custom, message: "frames must be even", path: ["frames"] });
|
|
752
796
|
}
|
|
797
|
+
if (revision.mode === "animate-skeleton" && !revision.keypointsFile) {
|
|
798
|
+
context.addIssue({
|
|
799
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
800
|
+
message: "animate-skeleton revisions require keypointsFile",
|
|
801
|
+
path: ["keypointsFile"]
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
for (const field of ["keypointsFile", "skeletonTemplate", "description"]) {
|
|
805
|
+
if (revision[field] !== void 0 && revision.mode !== "animate-skeleton") {
|
|
806
|
+
context.addIssue({
|
|
807
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
808
|
+
message: `${field} applies to animate-skeleton revisions only`,
|
|
809
|
+
path: [field]
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
}
|
|
753
813
|
});
|
|
754
|
-
var FRAME_SET_REVISION_MODES = ["animate", "animate-pixminimax", "interpolate", "edit-animation"];
|
|
814
|
+
var FRAME_SET_REVISION_MODES = ["animate", "animate-pixminimax", "animate-skeleton", "interpolate", "edit-animation"];
|
|
755
815
|
var MEMBER_SET_REVISION_MODES = ["reduce-colors", "correct-pixelart", "edit-animation"];
|
|
756
816
|
var StyleObjectSchema = import_zod.z.object({
|
|
757
817
|
/** Generation backend for this style. Omit to inherit the manifest default. */
|
|
@@ -1167,6 +1227,8 @@ var AssetSchema = import_zod.z.object({
|
|
|
1167
1227
|
portrait: CharacterPortraitSchema.optional(),
|
|
1168
1228
|
/** `character` styles: this asset re-clothes an existing loop's frames with a reference outfit. */
|
|
1169
1229
|
outfit: CharacterOutfitSchema.optional(),
|
|
1230
|
+
/** `map` styles only: draw this object in the style of a scene image. See `MapSceneSchema`. */
|
|
1231
|
+
scene: MapSceneSchema.optional(),
|
|
1170
1232
|
/** `character` styles, `standard` humanoid bases: this character's proportions, over the style's. */
|
|
1171
1233
|
proportions: CharacterProportionsSchema.optional(),
|
|
1172
1234
|
/**
|
|
@@ -1243,7 +1305,7 @@ var AssetSchema = import_zod.z.object({
|
|
|
1243
1305
|
path: ["revision"]
|
|
1244
1306
|
});
|
|
1245
1307
|
}
|
|
1246
|
-
const shapes = [asset.revision && "revision", asset.state && "state", asset.animation && "animation", asset.mirror && "mirror", asset.batch && "batch", asset.portrait && "portrait", asset.outfit && "outfit"].filter(Boolean);
|
|
1308
|
+
const shapes = [asset.revision && "revision", asset.state && "state", asset.animation && "animation", asset.mirror && "mirror", asset.batch && "batch", asset.portrait && "portrait", asset.outfit && "outfit", asset.scene && "scene"].filter(Boolean);
|
|
1247
1309
|
if (shapes.length > 1) {
|
|
1248
1310
|
context.addIssue({
|
|
1249
1311
|
code: import_zod.z.ZodIssueCode.custom,
|
|
@@ -1383,11 +1445,16 @@ var LockEntrySchema = import_zod.z.object({
|
|
|
1383
1445
|
paletteImageSha256: import_zod.z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1384
1446
|
dithering: RevisionDitheringSchema.optional(),
|
|
1385
1447
|
ditheringStrength: import_zod.z.number().min(0).max(10).optional(),
|
|
1386
|
-
|
|
1448
|
+
// 4-40 for animate/animate-pixminimax; animate-skeleton's own 3-15
|
|
1449
|
+
// range extends the floor down to 3, hence min(3) here rather than 4.
|
|
1450
|
+
frames: import_zod.z.number().int().min(3).max(40).optional(),
|
|
1387
1451
|
fps: import_zod.z.number().int().min(1).max(60).optional(),
|
|
1388
1452
|
lastFrameSha256: import_zod.z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1389
1453
|
direction: CharacterDirectionSchema.optional(),
|
|
1390
1454
|
enhancePrompt: import_zod.z.boolean().optional(),
|
|
1455
|
+
keypointsSha256: import_zod.z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1456
|
+
skeletonTemplate: import_zod.z.string().min(1).optional(),
|
|
1457
|
+
description: import_zod.z.string().min(1).optional(),
|
|
1391
1458
|
engine: import_zod.z.enum(["pro-flash"]).optional()
|
|
1392
1459
|
}).strict().nullable().default(null),
|
|
1393
1460
|
/** For a mirror: the asset it flips and a hash over that asset's output hashes when this was made. */
|
|
@@ -1574,7 +1641,7 @@ function exitCodeFor(err) {
|
|
|
1574
1641
|
}
|
|
1575
1642
|
|
|
1576
1643
|
// src/client.ts
|
|
1577
|
-
var
|
|
1644
|
+
var import_zod3 = require("zod");
|
|
1578
1645
|
|
|
1579
1646
|
// src/http.ts
|
|
1580
1647
|
var MAX_RETRIES = 4;
|
|
@@ -1624,262 +1691,289 @@ function fetchWithRetry(request, opts = {}) {
|
|
|
1624
1691
|
};
|
|
1625
1692
|
}
|
|
1626
1693
|
|
|
1694
|
+
// src/skeleton.ts
|
|
1695
|
+
var import_zod2 = require("zod");
|
|
1696
|
+
var SkeletonKeypointSchema = import_zod2.z.object({
|
|
1697
|
+
label: import_zod2.z.string().min(1),
|
|
1698
|
+
x: import_zod2.z.number().min(0).max(1),
|
|
1699
|
+
y: import_zod2.z.number().min(0).max(1),
|
|
1700
|
+
z_index: import_zod2.z.number(),
|
|
1701
|
+
depth: import_zod2.z.number().optional()
|
|
1702
|
+
}).strict();
|
|
1703
|
+
var SkeletonFrameSchema = import_zod2.z.array(SkeletonKeypointSchema).length(18);
|
|
1704
|
+
var SkeletonSetSchema = import_zod2.z.object({
|
|
1705
|
+
firstFrameKeypoints: SkeletonFrameSchema,
|
|
1706
|
+
frames: import_zod2.z.array(SkeletonFrameSchema).min(3).max(15)
|
|
1707
|
+
}).strict();
|
|
1708
|
+
function parseSkeletonSet(json, file) {
|
|
1709
|
+
const result = SkeletonSetSchema.safeParse(json);
|
|
1710
|
+
if (!result.success) {
|
|
1711
|
+
const issues = result.error.issues.slice(0, 4).map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join("; ");
|
|
1712
|
+
throw new Error(`revision keypoints file ${file} does not match the expected shape: ${issues}`);
|
|
1713
|
+
}
|
|
1714
|
+
return result.data;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1627
1717
|
// src/client.ts
|
|
1628
1718
|
var BASE = process.env.PIXELLAB_API_BASE ?? "https://api.pixellab.ai/v2";
|
|
1629
1719
|
var MAX_DOWNLOAD_BYTES = 64 * 1024 * 1024;
|
|
1630
|
-
var BalanceResponseSchema =
|
|
1631
|
-
credits:
|
|
1632
|
-
subscription:
|
|
1633
|
-
generations:
|
|
1634
|
-
total:
|
|
1635
|
-
plan:
|
|
1720
|
+
var BalanceResponseSchema = import_zod3.z.object({
|
|
1721
|
+
credits: import_zod3.z.object({ usd: import_zod3.z.number() }).passthrough(),
|
|
1722
|
+
subscription: import_zod3.z.object({
|
|
1723
|
+
generations: import_zod3.z.number(),
|
|
1724
|
+
total: import_zod3.z.number(),
|
|
1725
|
+
plan: import_zod3.z.string().nullable().optional()
|
|
1636
1726
|
}).passthrough()
|
|
1637
1727
|
}).passthrough();
|
|
1638
|
-
var ObjectSubmitSchema =
|
|
1639
|
-
background_job_id:
|
|
1640
|
-
object_id:
|
|
1641
|
-
status:
|
|
1642
|
-
n_frames:
|
|
1728
|
+
var ObjectSubmitSchema = import_zod3.z.object({
|
|
1729
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1730
|
+
object_id: import_zod3.z.string().min(1),
|
|
1731
|
+
status: import_zod3.z.string().default("queued"),
|
|
1732
|
+
n_frames: import_zod3.z.number().int().min(0)
|
|
1643
1733
|
}).passthrough();
|
|
1644
|
-
var MapSubmitSchema =
|
|
1645
|
-
background_job_id:
|
|
1646
|
-
object_id:
|
|
1647
|
-
status:
|
|
1734
|
+
var MapSubmitSchema = import_zod3.z.object({
|
|
1735
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1736
|
+
object_id: import_zod3.z.string().min(1),
|
|
1737
|
+
status: import_zod3.z.string().default("processing")
|
|
1648
1738
|
}).passthrough();
|
|
1649
|
-
var UsageSchema =
|
|
1650
|
-
type:
|
|
1651
|
-
usd:
|
|
1652
|
-
generations:
|
|
1739
|
+
var UsageSchema = import_zod3.z.object({
|
|
1740
|
+
type: import_zod3.z.string().optional(),
|
|
1741
|
+
usd: import_zod3.z.number().nullable().optional(),
|
|
1742
|
+
generations: import_zod3.z.number().nullable().optional()
|
|
1653
1743
|
}).passthrough().nullable().optional();
|
|
1654
|
-
var TilesSubmitSchema =
|
|
1655
|
-
tile_id:
|
|
1656
|
-
background_job_id:
|
|
1657
|
-
status:
|
|
1744
|
+
var TilesSubmitSchema = import_zod3.z.object({
|
|
1745
|
+
tile_id: import_zod3.z.string().min(1),
|
|
1746
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1747
|
+
status: import_zod3.z.literal("processing").default("processing")
|
|
1658
1748
|
}).passthrough();
|
|
1659
|
-
var TilesProSchema =
|
|
1660
|
-
storage_urls:
|
|
1661
|
-
kind:
|
|
1662
|
-
tile_rules:
|
|
1749
|
+
var TilesProSchema = import_zod3.z.object({
|
|
1750
|
+
storage_urls: import_zod3.z.record(import_zod3.z.string()),
|
|
1751
|
+
kind: import_zod3.z.string().nullable().default(null),
|
|
1752
|
+
tile_rules: import_zod3.z.record(import_zod3.z.unknown()).nullable().optional()
|
|
1663
1753
|
}).passthrough();
|
|
1664
|
-
var TilesetSubmitSchema =
|
|
1665
|
-
tileset_id:
|
|
1666
|
-
background_job_id:
|
|
1667
|
-
status:
|
|
1754
|
+
var TilesetSubmitSchema = import_zod3.z.object({
|
|
1755
|
+
tileset_id: import_zod3.z.string().min(1),
|
|
1756
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1757
|
+
status: import_zod3.z.literal("processing").default("processing")
|
|
1668
1758
|
}).passthrough();
|
|
1669
|
-
var TilesetTileSchema =
|
|
1670
|
-
id:
|
|
1671
|
-
name:
|
|
1672
|
-
image:
|
|
1673
|
-
corners:
|
|
1674
|
-
pattern_4x4:
|
|
1675
|
-
row_0:
|
|
1676
|
-
row_1:
|
|
1677
|
-
row_2:
|
|
1678
|
-
row_3:
|
|
1759
|
+
var TilesetTileSchema = import_zod3.z.object({
|
|
1760
|
+
id: import_zod3.z.string().min(1),
|
|
1761
|
+
name: import_zod3.z.string(),
|
|
1762
|
+
image: import_zod3.z.object({ base64: import_zod3.z.string().min(1), format: import_zod3.z.string().default("png") }).passthrough(),
|
|
1763
|
+
corners: import_zod3.z.object({ NW: import_zod3.z.string(), NE: import_zod3.z.string(), SW: import_zod3.z.string(), SE: import_zod3.z.string() }).passthrough(),
|
|
1764
|
+
pattern_4x4: import_zod3.z.object({
|
|
1765
|
+
row_0: import_zod3.z.array(import_zod3.z.number()),
|
|
1766
|
+
row_1: import_zod3.z.array(import_zod3.z.number()),
|
|
1767
|
+
row_2: import_zod3.z.array(import_zod3.z.number()),
|
|
1768
|
+
row_3: import_zod3.z.array(import_zod3.z.number())
|
|
1679
1769
|
}).passthrough()
|
|
1680
1770
|
}).passthrough();
|
|
1681
|
-
var TilesetGetSchema =
|
|
1682
|
-
tileset:
|
|
1683
|
-
total_tiles:
|
|
1684
|
-
tile_size:
|
|
1685
|
-
terrain_types:
|
|
1686
|
-
tiles:
|
|
1771
|
+
var TilesetGetSchema = import_zod3.z.object({
|
|
1772
|
+
tileset: import_zod3.z.object({
|
|
1773
|
+
total_tiles: import_zod3.z.number().int().min(1),
|
|
1774
|
+
tile_size: import_zod3.z.object({ width: import_zod3.z.number().int().positive(), height: import_zod3.z.number().int().positive() }).passthrough(),
|
|
1775
|
+
terrain_types: import_zod3.z.array(import_zod3.z.string()),
|
|
1776
|
+
tiles: import_zod3.z.array(TilesetTileSchema).min(1)
|
|
1687
1777
|
}).passthrough(),
|
|
1688
1778
|
usage: UsageSchema
|
|
1689
1779
|
}).passthrough();
|
|
1690
|
-
var IsometricTileSubmitSchema =
|
|
1691
|
-
tile_id:
|
|
1692
|
-
background_job_id:
|
|
1693
|
-
status:
|
|
1780
|
+
var IsometricTileSubmitSchema = import_zod3.z.object({
|
|
1781
|
+
tile_id: import_zod3.z.string().min(1),
|
|
1782
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1783
|
+
status: import_zod3.z.literal("processing").default("processing")
|
|
1694
1784
|
}).passthrough();
|
|
1695
|
-
var IsometricTileGetSchema =
|
|
1696
|
-
image:
|
|
1785
|
+
var IsometricTileGetSchema = import_zod3.z.object({
|
|
1786
|
+
image: import_zod3.z.object({ base64: import_zod3.z.string().min(1), format: import_zod3.z.string().default("png") }).passthrough(),
|
|
1697
1787
|
usage: UsageSchema
|
|
1698
1788
|
}).passthrough();
|
|
1699
|
-
var UiAssetSubmitSchema =
|
|
1700
|
-
ui_asset_id:
|
|
1701
|
-
background_job_id:
|
|
1702
|
-
status:
|
|
1789
|
+
var UiAssetSubmitSchema = import_zod3.z.object({
|
|
1790
|
+
ui_asset_id: import_zod3.z.string().min(1),
|
|
1791
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1792
|
+
status: import_zod3.z.string().default("processing"),
|
|
1703
1793
|
usage: UsageSchema
|
|
1704
1794
|
}).passthrough();
|
|
1705
|
-
var UiAssetGetSchema =
|
|
1706
|
-
id:
|
|
1707
|
-
status:
|
|
1708
|
-
image_url:
|
|
1709
|
-
progress_percent:
|
|
1710
|
-
eta_seconds:
|
|
1795
|
+
var UiAssetGetSchema = import_zod3.z.object({
|
|
1796
|
+
id: import_zod3.z.string().min(1),
|
|
1797
|
+
status: import_zod3.z.string().nullable().default(null),
|
|
1798
|
+
image_url: import_zod3.z.string().nullable().optional(),
|
|
1799
|
+
progress_percent: import_zod3.z.number().nullable().optional(),
|
|
1800
|
+
eta_seconds: import_zod3.z.number().nullable().optional()
|
|
1711
1801
|
}).passthrough();
|
|
1712
|
-
var RevisionJobSubmitSchema =
|
|
1713
|
-
background_job_id:
|
|
1714
|
-
status:
|
|
1802
|
+
var RevisionJobSubmitSchema = import_zod3.z.object({
|
|
1803
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1804
|
+
status: import_zod3.z.string().default("processing")
|
|
1715
1805
|
}).passthrough();
|
|
1716
|
-
var ObjectAnimationGroupSchema =
|
|
1717
|
-
animation_group_id:
|
|
1718
|
-
display_name:
|
|
1719
|
-
description:
|
|
1720
|
-
frame_count:
|
|
1721
|
-
directions:
|
|
1722
|
-
|
|
1723
|
-
direction:
|
|
1724
|
-
storage_urls:
|
|
1725
|
-
created_at:
|
|
1806
|
+
var ObjectAnimationGroupSchema = import_zod3.z.object({
|
|
1807
|
+
animation_group_id: import_zod3.z.string().min(1),
|
|
1808
|
+
display_name: import_zod3.z.string().nullable().default(null),
|
|
1809
|
+
description: import_zod3.z.string().default(""),
|
|
1810
|
+
frame_count: import_zod3.z.number().int().default(0),
|
|
1811
|
+
directions: import_zod3.z.array(
|
|
1812
|
+
import_zod3.z.object({
|
|
1813
|
+
direction: import_zod3.z.string(),
|
|
1814
|
+
storage_urls: import_zod3.z.record(import_zod3.z.unknown()).default({}),
|
|
1815
|
+
created_at: import_zod3.z.string()
|
|
1726
1816
|
}).passthrough()
|
|
1727
1817
|
).default([])
|
|
1728
1818
|
}).passthrough();
|
|
1729
|
-
var PixelLabObjectSchema =
|
|
1730
|
-
id:
|
|
1731
|
-
name:
|
|
1732
|
-
state_name:
|
|
1733
|
-
prompt:
|
|
1734
|
-
size:
|
|
1735
|
-
directions:
|
|
1736
|
-
created_at:
|
|
1737
|
-
view:
|
|
1738
|
-
preview_url:
|
|
1739
|
-
rotation_urls:
|
|
1740
|
-
frame_urls:
|
|
1741
|
-
tags:
|
|
1742
|
-
status:
|
|
1743
|
-
progress_percent:
|
|
1744
|
-
eta_seconds:
|
|
1745
|
-
group_id:
|
|
1746
|
-
animations:
|
|
1819
|
+
var PixelLabObjectSchema = import_zod3.z.object({
|
|
1820
|
+
id: import_zod3.z.string().min(1),
|
|
1821
|
+
name: import_zod3.z.string().nullable().default(null),
|
|
1822
|
+
state_name: import_zod3.z.string().nullable().optional(),
|
|
1823
|
+
prompt: import_zod3.z.string().default(""),
|
|
1824
|
+
size: import_zod3.z.object({ width: import_zod3.z.number().int().positive(), height: import_zod3.z.number().int().positive() }),
|
|
1825
|
+
directions: import_zod3.z.number().default(0),
|
|
1826
|
+
created_at: import_zod3.z.string(),
|
|
1827
|
+
view: import_zod3.z.string().nullable().default(null),
|
|
1828
|
+
preview_url: import_zod3.z.string().nullable().optional(),
|
|
1829
|
+
rotation_urls: import_zod3.z.record(import_zod3.z.string().nullable()).nullable().optional(),
|
|
1830
|
+
frame_urls: import_zod3.z.array(import_zod3.z.string()).nullable().optional(),
|
|
1831
|
+
tags: import_zod3.z.array(import_zod3.z.string()).default([]),
|
|
1832
|
+
status: import_zod3.z.string().nullable().default(null),
|
|
1833
|
+
progress_percent: import_zod3.z.number().nullable().optional(),
|
|
1834
|
+
eta_seconds: import_zod3.z.number().nullable().optional(),
|
|
1835
|
+
group_id: import_zod3.z.string().nullable().optional(),
|
|
1836
|
+
animations: import_zod3.z.array(ObjectAnimationGroupSchema).default([])
|
|
1747
1837
|
}).passthrough();
|
|
1748
|
-
var MapObjectSchema =
|
|
1749
|
-
object_id:
|
|
1750
|
-
status:
|
|
1751
|
-
description:
|
|
1752
|
-
width:
|
|
1753
|
-
height:
|
|
1754
|
-
download_url:
|
|
1838
|
+
var MapObjectSchema = import_zod3.z.object({
|
|
1839
|
+
object_id: import_zod3.z.string().min(1),
|
|
1840
|
+
status: import_zod3.z.string(),
|
|
1841
|
+
description: import_zod3.z.string().nullable().default(null),
|
|
1842
|
+
width: import_zod3.z.number().nullable().default(null),
|
|
1843
|
+
height: import_zod3.z.number().nullable().default(null),
|
|
1844
|
+
download_url: import_zod3.z.string().nullable().default(null)
|
|
1755
1845
|
}).passthrough();
|
|
1756
|
-
var ObjectListSchema =
|
|
1757
|
-
var PixfluxResponseSchema =
|
|
1758
|
-
var ReduceColorsResponseSchema =
|
|
1759
|
-
images:
|
|
1760
|
-
palette:
|
|
1761
|
-
n_colors:
|
|
1762
|
-
usage:
|
|
1846
|
+
var ObjectListSchema = import_zod3.z.object({ objects: import_zod3.z.array(PixelLabObjectSchema), total: import_zod3.z.number().int().min(0) }).passthrough();
|
|
1847
|
+
var PixfluxResponseSchema = import_zod3.z.object({ image: import_zod3.z.object({ base64: import_zod3.z.string().min(1) }).passthrough(), usage: import_zod3.z.unknown().optional() }).passthrough();
|
|
1848
|
+
var ReduceColorsResponseSchema = import_zod3.z.object({
|
|
1849
|
+
images: import_zod3.z.array(import_zod3.z.object({ base64: import_zod3.z.string().min(1) }).passthrough()).min(1),
|
|
1850
|
+
palette: import_zod3.z.object({ base64: import_zod3.z.string().min(1) }).passthrough(),
|
|
1851
|
+
n_colors: import_zod3.z.number().int(),
|
|
1852
|
+
usage: import_zod3.z.unknown().optional()
|
|
1763
1853
|
}).passthrough();
|
|
1764
|
-
var CorrectPixelartResponseSchema =
|
|
1765
|
-
images:
|
|
1766
|
-
usage:
|
|
1854
|
+
var CorrectPixelartResponseSchema = import_zod3.z.object({
|
|
1855
|
+
images: import_zod3.z.array(import_zod3.z.object({ base64: import_zod3.z.string().min(1) }).passthrough()).min(1),
|
|
1856
|
+
usage: import_zod3.z.unknown().optional()
|
|
1767
1857
|
}).passthrough();
|
|
1768
|
-
var ProFlashImageSubmitSchema =
|
|
1769
|
-
background_job_id:
|
|
1770
|
-
image_id:
|
|
1771
|
-
source_image_id:
|
|
1772
|
-
status:
|
|
1773
|
-
estimated_generations:
|
|
1774
|
-
usage:
|
|
1858
|
+
var ProFlashImageSubmitSchema = import_zod3.z.object({
|
|
1859
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1860
|
+
image_id: import_zod3.z.string().min(1),
|
|
1861
|
+
source_image_id: import_zod3.z.string().min(1),
|
|
1862
|
+
status: import_zod3.z.string().default("processing"),
|
|
1863
|
+
estimated_generations: import_zod3.z.number().nullable().optional(),
|
|
1864
|
+
usage: import_zod3.z.unknown().optional()
|
|
1775
1865
|
}).passthrough();
|
|
1776
|
-
var UnzoomResponseSchema =
|
|
1777
|
-
image:
|
|
1778
|
-
original_size:
|
|
1779
|
-
unzoomed_size:
|
|
1780
|
-
zoom_factor_detected:
|
|
1781
|
-
usage:
|
|
1866
|
+
var UnzoomResponseSchema = import_zod3.z.object({
|
|
1867
|
+
image: import_zod3.z.object({ base64: import_zod3.z.string().min(1) }).passthrough(),
|
|
1868
|
+
original_size: import_zod3.z.object({ width: import_zod3.z.number().int(), height: import_zod3.z.number().int() }).passthrough(),
|
|
1869
|
+
unzoomed_size: import_zod3.z.object({ width: import_zod3.z.number().int(), height: import_zod3.z.number().int() }).passthrough(),
|
|
1870
|
+
zoom_factor_detected: import_zod3.z.number(),
|
|
1871
|
+
usage: import_zod3.z.unknown().optional()
|
|
1782
1872
|
}).passthrough();
|
|
1783
|
-
var FontJobSchema =
|
|
1784
|
-
job_id:
|
|
1785
|
-
status:
|
|
1786
|
-
glyph_px:
|
|
1787
|
-
download_atlas_url:
|
|
1788
|
-
download_ttf_url:
|
|
1789
|
-
usage:
|
|
1873
|
+
var FontJobSchema = import_zod3.z.object({
|
|
1874
|
+
job_id: import_zod3.z.string().min(1),
|
|
1875
|
+
status: import_zod3.z.string(),
|
|
1876
|
+
glyph_px: import_zod3.z.number().int().nullable().optional(),
|
|
1877
|
+
download_atlas_url: import_zod3.z.string().nullable().optional(),
|
|
1878
|
+
download_ttf_url: import_zod3.z.string().nullable().optional(),
|
|
1879
|
+
usage: import_zod3.z.unknown().optional()
|
|
1790
1880
|
}).passthrough();
|
|
1791
|
-
var SelectFramesSchema =
|
|
1792
|
-
var
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1881
|
+
var SelectFramesSchema = import_zod3.z.object({ created_object_ids: import_zod3.z.array(import_zod3.z.string()) }).passthrough();
|
|
1882
|
+
var EstimateSkeletonResponseSchema = import_zod3.z.object({
|
|
1883
|
+
keypoints: import_zod3.z.array(SkeletonKeypointSchema).length(18),
|
|
1884
|
+
usage: import_zod3.z.unknown().optional()
|
|
1885
|
+
}).passthrough();
|
|
1886
|
+
var CharacterSubmitSchema = import_zod3.z.object({
|
|
1887
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1888
|
+
character_id: import_zod3.z.string().min(1),
|
|
1889
|
+
status: import_zod3.z.string().default("processing"),
|
|
1796
1890
|
usage: UsageSchema
|
|
1797
1891
|
}).passthrough();
|
|
1798
|
-
var AnimateSubmitSchema =
|
|
1799
|
-
background_job_ids:
|
|
1800
|
-
directions:
|
|
1801
|
-
status:
|
|
1892
|
+
var AnimateSubmitSchema = import_zod3.z.object({
|
|
1893
|
+
background_job_ids: import_zod3.z.array(import_zod3.z.string()),
|
|
1894
|
+
directions: import_zod3.z.array(import_zod3.z.string()),
|
|
1895
|
+
status: import_zod3.z.string().default("processing"),
|
|
1802
1896
|
usage: UsageSchema
|
|
1803
1897
|
}).passthrough();
|
|
1804
|
-
var ObjectProSubmitSchema =
|
|
1805
|
-
object_id:
|
|
1806
|
-
background_job_id:
|
|
1807
|
-
status:
|
|
1898
|
+
var ObjectProSubmitSchema = import_zod3.z.object({
|
|
1899
|
+
object_id: import_zod3.z.string().min(1),
|
|
1900
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1901
|
+
status: import_zod3.z.string().default("processing"),
|
|
1808
1902
|
usage: UsageSchema
|
|
1809
1903
|
}).passthrough();
|
|
1810
|
-
var DirectionSubmissionSchema =
|
|
1811
|
-
direction:
|
|
1812
|
-
status:
|
|
1813
|
-
background_job_id:
|
|
1814
|
-
animation_id:
|
|
1904
|
+
var DirectionSubmissionSchema = import_zod3.z.object({
|
|
1905
|
+
direction: import_zod3.z.string(),
|
|
1906
|
+
status: import_zod3.z.string(),
|
|
1907
|
+
background_job_id: import_zod3.z.string().nullable().default(null),
|
|
1908
|
+
animation_id: import_zod3.z.string().nullable().default(null)
|
|
1815
1909
|
}).passthrough();
|
|
1816
|
-
var AnimateObjectSubmitSchema =
|
|
1817
|
-
animation_group_id:
|
|
1818
|
-
object_id:
|
|
1819
|
-
mode:
|
|
1820
|
-
frame_count:
|
|
1821
|
-
display_name:
|
|
1822
|
-
description:
|
|
1823
|
-
submissions:
|
|
1910
|
+
var AnimateObjectSubmitSchema = import_zod3.z.object({
|
|
1911
|
+
animation_group_id: import_zod3.z.string().min(1),
|
|
1912
|
+
object_id: import_zod3.z.string().min(1),
|
|
1913
|
+
mode: import_zod3.z.string(),
|
|
1914
|
+
frame_count: import_zod3.z.number().int(),
|
|
1915
|
+
display_name: import_zod3.z.string().nullable().default(null),
|
|
1916
|
+
description: import_zod3.z.string().default(""),
|
|
1917
|
+
submissions: import_zod3.z.array(DirectionSubmissionSchema),
|
|
1824
1918
|
usage: UsageSchema
|
|
1825
1919
|
}).passthrough();
|
|
1826
|
-
var PortraitSubmitSchema =
|
|
1827
|
-
background_job_id:
|
|
1828
|
-
status:
|
|
1920
|
+
var PortraitSubmitSchema = import_zod3.z.object({
|
|
1921
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1922
|
+
status: import_zod3.z.string().default("processing"),
|
|
1829
1923
|
usage: UsageSchema
|
|
1830
1924
|
}).passthrough();
|
|
1831
|
-
var PortraitJobSchema =
|
|
1832
|
-
status:
|
|
1833
|
-
download_url:
|
|
1834
|
-
width:
|
|
1835
|
-
height:
|
|
1925
|
+
var PortraitJobSchema = import_zod3.z.object({
|
|
1926
|
+
status: import_zod3.z.string(),
|
|
1927
|
+
download_url: import_zod3.z.string().nullable().optional(),
|
|
1928
|
+
width: import_zod3.z.number().int().nullable().optional(),
|
|
1929
|
+
height: import_zod3.z.number().int().nullable().optional()
|
|
1836
1930
|
}).passthrough();
|
|
1837
|
-
var SetPortraitSchema =
|
|
1838
|
-
character_id:
|
|
1839
|
-
size:
|
|
1840
|
-
url:
|
|
1931
|
+
var SetPortraitSchema = import_zod3.z.object({
|
|
1932
|
+
character_id: import_zod3.z.string().min(1),
|
|
1933
|
+
size: import_zod3.z.number().int().positive(),
|
|
1934
|
+
url: import_zod3.z.string().min(1),
|
|
1841
1935
|
usage: UsageSchema
|
|
1842
1936
|
}).passthrough();
|
|
1843
|
-
var TransferOutfitSubmitSchema =
|
|
1844
|
-
background_job_id:
|
|
1845
|
-
status:
|
|
1937
|
+
var TransferOutfitSubmitSchema = import_zod3.z.object({
|
|
1938
|
+
background_job_id: import_zod3.z.string().min(1),
|
|
1939
|
+
status: import_zod3.z.string().default("processing"),
|
|
1846
1940
|
usage: UsageSchema
|
|
1847
1941
|
}).passthrough();
|
|
1848
|
-
var CharacterAnimationDirectionSchema =
|
|
1849
|
-
direction:
|
|
1850
|
-
frame_count:
|
|
1851
|
-
frames:
|
|
1942
|
+
var CharacterAnimationDirectionSchema = import_zod3.z.object({
|
|
1943
|
+
direction: import_zod3.z.string(),
|
|
1944
|
+
frame_count: import_zod3.z.number().int().min(0),
|
|
1945
|
+
frames: import_zod3.z.array(import_zod3.z.string())
|
|
1852
1946
|
}).passthrough();
|
|
1853
|
-
var CharacterAnimationSchema2 =
|
|
1854
|
-
animation_type:
|
|
1855
|
-
display_name:
|
|
1856
|
-
animation_group_id:
|
|
1857
|
-
directions:
|
|
1947
|
+
var CharacterAnimationSchema2 = import_zod3.z.object({
|
|
1948
|
+
animation_type: import_zod3.z.string(),
|
|
1949
|
+
display_name: import_zod3.z.string().nullable().optional(),
|
|
1950
|
+
animation_group_id: import_zod3.z.string().nullable().optional(),
|
|
1951
|
+
directions: import_zod3.z.array(CharacterAnimationDirectionSchema)
|
|
1858
1952
|
}).passthrough();
|
|
1859
|
-
var CharacterSchema =
|
|
1860
|
-
id:
|
|
1861
|
-
name:
|
|
1862
|
-
state_name:
|
|
1863
|
-
prompt:
|
|
1864
|
-
size:
|
|
1865
|
-
directions:
|
|
1866
|
-
created_at:
|
|
1867
|
-
updated_at:
|
|
1868
|
-
animation_count:
|
|
1869
|
-
template_id:
|
|
1870
|
-
view:
|
|
1871
|
-
status:
|
|
1872
|
-
rotation_urls:
|
|
1873
|
-
tags:
|
|
1874
|
-
group_id:
|
|
1875
|
-
animations:
|
|
1876
|
-
preview_url:
|
|
1953
|
+
var CharacterSchema = import_zod3.z.object({
|
|
1954
|
+
id: import_zod3.z.string().min(1),
|
|
1955
|
+
name: import_zod3.z.string().default(""),
|
|
1956
|
+
state_name: import_zod3.z.string().nullable().optional(),
|
|
1957
|
+
prompt: import_zod3.z.string().default(""),
|
|
1958
|
+
size: import_zod3.z.object({ width: import_zod3.z.number().int().positive(), height: import_zod3.z.number().int().positive() }),
|
|
1959
|
+
directions: import_zod3.z.number().int(),
|
|
1960
|
+
created_at: import_zod3.z.string(),
|
|
1961
|
+
updated_at: import_zod3.z.string().nullable().optional(),
|
|
1962
|
+
animation_count: import_zod3.z.number().int().default(0),
|
|
1963
|
+
template_id: import_zod3.z.string().default("mannequin"),
|
|
1964
|
+
view: import_zod3.z.string().nullable().optional(),
|
|
1965
|
+
status: import_zod3.z.string().default("completed"),
|
|
1966
|
+
rotation_urls: import_zod3.z.record(import_zod3.z.string().nullable()).nullable().optional(),
|
|
1967
|
+
tags: import_zod3.z.array(import_zod3.z.string()).default([]),
|
|
1968
|
+
group_id: import_zod3.z.string().nullable().optional(),
|
|
1969
|
+
animations: import_zod3.z.array(CharacterAnimationSchema2).default([]),
|
|
1970
|
+
preview_url: import_zod3.z.string().nullable().optional()
|
|
1877
1971
|
}).passthrough();
|
|
1878
|
-
var CharacterListSchema =
|
|
1879
|
-
var BackgroundJobSchema =
|
|
1880
|
-
id:
|
|
1881
|
-
status:
|
|
1882
|
-
last_response:
|
|
1972
|
+
var CharacterListSchema = import_zod3.z.object({ characters: import_zod3.z.array(CharacterSchema), total: import_zod3.z.number().int().min(0) }).passthrough();
|
|
1973
|
+
var BackgroundJobSchema = import_zod3.z.object({
|
|
1974
|
+
id: import_zod3.z.string(),
|
|
1975
|
+
status: import_zod3.z.string(),
|
|
1976
|
+
last_response: import_zod3.z.record(import_zod3.z.unknown()).nullable().optional(),
|
|
1883
1977
|
/**
|
|
1884
1978
|
* The billed amount, confirmed live for a `map` object and a standard
|
|
1885
1979
|
* character base (docs/ENDPOINTS.md, "Limits and billing"); duplicated at
|
|
@@ -1887,7 +1981,7 @@ var BackgroundJobSchema = import_zod2.z.object({
|
|
|
1887
1981
|
*/
|
|
1888
1982
|
usage: UsageSchema
|
|
1889
1983
|
}).passthrough();
|
|
1890
|
-
var DeleteAnimationsSchema =
|
|
1984
|
+
var DeleteAnimationsSchema = import_zod3.z.object({ success: import_zod3.z.boolean(), deleted_count: import_zod3.z.number().int().default(0), error: import_zod3.z.string().nullable().optional() }).passthrough();
|
|
1891
1985
|
function validateResponse(schema, raw, operation) {
|
|
1892
1986
|
const parsed = schema.safeParse(raw);
|
|
1893
1987
|
if (parsed.success) return parsed.data;
|
|
@@ -2007,6 +2101,12 @@ var PixelLabClient = class {
|
|
|
2007
2101
|
if (args.shading) body.shading = args.shading;
|
|
2008
2102
|
if (args.detail) body.detail = args.detail;
|
|
2009
2103
|
if (args.seed != null) body.seed = args.seed;
|
|
2104
|
+
if (args.scene) {
|
|
2105
|
+
const encode = (image) => ({ type: "base64", base64: image.base64, format: image.format });
|
|
2106
|
+
const placement = args.scene.placement;
|
|
2107
|
+
body.background_image = encode(args.scene.image);
|
|
2108
|
+
body.inpainting = placement.type === "mask" ? { type: "mask", mask_image: encode(placement.mask) } : { type: placement.type, fraction: placement.fraction };
|
|
2109
|
+
}
|
|
2010
2110
|
return validateResponse(
|
|
2011
2111
|
MapSubmitSchema,
|
|
2012
2112
|
await this.request("/map-objects", { method: "POST", body: JSON.stringify(body) }),
|
|
@@ -2918,6 +3018,61 @@ var PixelLabClient = class {
|
|
|
2918
3018
|
"animate-pixminimax"
|
|
2919
3019
|
);
|
|
2920
3020
|
}
|
|
3021
|
+
/**
|
|
3022
|
+
* `/animate-with-skeleton-v3`, beta (tier 1 subscription or higher): poses
|
|
3023
|
+
* one reference image frame-by-frame from a supplied skeleton per frame,
|
|
3024
|
+
* rather than a text motion description. Confirmed against the live
|
|
3025
|
+
* `animate_with_skeleton_v3` MCP tool schema (the same authoritative
|
|
3026
|
+
* source this codebase already treats as ground truth for the
|
|
3027
|
+
* character/object family) — `action`/`description` are both real,
|
|
3028
|
+
* optional wire fields, contrary to an initial guess that this endpoint
|
|
3029
|
+
* took no text input at all; `direction`/`keypoints`/`firstFrameKeypoints`
|
|
3030
|
+
* are required. The example keypoint from that same tool schema,
|
|
3031
|
+
* `{"label": "RIGHT KNEE", "x": 0.52, "y": 0.71, "z_index": 9}`, is what
|
|
3032
|
+
* `SkeletonKeypointSchema` (`src/skeleton.ts`) models. Same
|
|
3033
|
+
* unverified-completed-shape caveat as `animateWithTextV3`/
|
|
3034
|
+
* `animatePixminimax` above — this endpoint has never been called against
|
|
3035
|
+
* a live account by this codebase.
|
|
3036
|
+
*/
|
|
3037
|
+
async animateWithSkeletonV3(args) {
|
|
3038
|
+
const body = {
|
|
3039
|
+
first_frame: args.firstFrame,
|
|
3040
|
+
first_frame_keypoints: args.firstFrameKeypoints,
|
|
3041
|
+
keypoints: args.keypoints,
|
|
3042
|
+
direction: args.direction
|
|
3043
|
+
};
|
|
3044
|
+
if (args.templateId) body.template_id = args.templateId;
|
|
3045
|
+
if (args.action) body.action = args.action;
|
|
3046
|
+
if (args.description) body.description = args.description;
|
|
3047
|
+
if (args.seed != null) body.seed = args.seed;
|
|
3048
|
+
if (args.noBackground != null) body.no_background = args.noBackground;
|
|
3049
|
+
return validateResponse(
|
|
3050
|
+
RevisionJobSubmitSchema,
|
|
3051
|
+
await this.request("/animate-with-skeleton-v3", { method: "POST", body: JSON.stringify(body) }),
|
|
3052
|
+
"animate-with-skeleton-v3"
|
|
3053
|
+
);
|
|
3054
|
+
}
|
|
3055
|
+
/**
|
|
3056
|
+
* `/estimate-skeleton`: auto-derives a reference image's own 18-joint
|
|
3057
|
+
* keypoints, directly usable as `animateWithSkeletonV3`'s
|
|
3058
|
+
* `firstFrameKeypoints` (or, run against a candidate pose image, as one
|
|
3059
|
+
* entry of its `keypoints` sequence). Not called anywhere in this
|
|
3060
|
+
* codebase's own submit/poll pipeline — deliberately kept outside it (see
|
|
3061
|
+
* `runEstimateSkeleton` in `src/cli/commands`) so the only PixelLab
|
|
3062
|
+
* endpoint composed into `animate-with-skeleton-v3`'s submission is that
|
|
3063
|
+
* one endpoint itself, not two unverified calls chained together.
|
|
3064
|
+
* Synchronous per this endpoint's own framing; unverified against a live
|
|
3065
|
+
* account (see `EstimateSkeletonResponseSchema`'s own caveat).
|
|
3066
|
+
*/
|
|
3067
|
+
async estimateSkeleton(args) {
|
|
3068
|
+
const body = { image: args.image };
|
|
3069
|
+
const res = validateResponse(
|
|
3070
|
+
EstimateSkeletonResponseSchema,
|
|
3071
|
+
await this.request("/estimate-skeleton", { method: "POST", body: JSON.stringify(body) }),
|
|
3072
|
+
"estimate-skeleton"
|
|
3073
|
+
);
|
|
3074
|
+
return { keypoints: res.keypoints, usage: res.usage };
|
|
3075
|
+
}
|
|
2921
3076
|
async getBackgroundJob(jobId) {
|
|
2922
3077
|
const raw = await this.request(`/background-jobs/${encodeURIComponent(jobId)}`);
|
|
2923
3078
|
return validateResponse(BackgroundJobSchema, raw, "background-jobs/{id}");
|
|
@@ -3574,6 +3729,11 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
3574
3729
|
uiPieces: spec.uiPieces,
|
|
3575
3730
|
uiElements: spec.uiElements,
|
|
3576
3731
|
uiColorPalette: spec.uiColorPalette,
|
|
3732
|
+
// Scene and mask enter as their bytes' hashes, never their paths.
|
|
3733
|
+
scene: spec.scene ? {
|
|
3734
|
+
image: spec.scene.sha256,
|
|
3735
|
+
placement: spec.scene.placement.type === "mask" ? { type: "mask", mask: spec.scene.placement.sha256 } : spec.scene.placement
|
|
3736
|
+
} : void 0,
|
|
3577
3737
|
styleTraits: spec.styleTraits,
|
|
3578
3738
|
styleImages: styleImageHashes,
|
|
3579
3739
|
// A character family: the engine and rotations of a base, the parent's
|
|
@@ -3652,6 +3812,9 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
3652
3812
|
lastFrameSha256: spec.revision.lastFrameSha256,
|
|
3653
3813
|
direction: spec.revision.direction,
|
|
3654
3814
|
enhancePrompt: spec.revision.enhancePrompt,
|
|
3815
|
+
keypointsSha256: spec.revision.keypointsSha256,
|
|
3816
|
+
skeletonTemplate: spec.revision.skeletonTemplate,
|
|
3817
|
+
description: spec.revision.description,
|
|
3655
3818
|
engine: spec.revision.engine
|
|
3656
3819
|
} : void 0
|
|
3657
3820
|
})
|
|
@@ -3740,6 +3903,18 @@ function objectProCost(spec) {
|
|
|
3740
3903
|
const south = object.reference;
|
|
3741
3904
|
return south ? proFlashObjectCost(south.width, south.height, object.directions, true) : proFlashObjectCost(spec.width, spec.height, object.directions, false);
|
|
3742
3905
|
}
|
|
3906
|
+
function animateSkeletonCost(frames) {
|
|
3907
|
+
const anchors = [[3, 2], [8, 3], [15, 4]];
|
|
3908
|
+
for (let i = 0; i < anchors.length - 1; i++) {
|
|
3909
|
+
const [lowFrames, lowCost] = anchors[i];
|
|
3910
|
+
const [highFrames, highCost] = anchors[i + 1];
|
|
3911
|
+
if (frames >= lowFrames && frames <= highFrames) {
|
|
3912
|
+
const t = (frames - lowFrames) / (highFrames - lowFrames);
|
|
3913
|
+
return lowCost + t * (highCost - lowCost);
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
return frames <= anchors[0][0] ? anchors[0][1] : anchors[anchors.length - 1][1];
|
|
3917
|
+
}
|
|
3743
3918
|
var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
|
|
3744
3919
|
var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
|
|
3745
3920
|
function encodeAnimationJob(job) {
|
|
@@ -3790,6 +3965,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
3790
3965
|
supports(generator) {
|
|
3791
3966
|
return generator === "1dir" || generator === "map" || generator === "pixflux" || generator === "tiles" || generator === "terrain" || generator === "imagePro" || generator === "character" || generator === "isometricTile" || generator === "objectPro" || generator === "uiAsset" || generator === "uiElement" || generator === "imageProFlash";
|
|
3792
3967
|
}
|
|
3968
|
+
/** `/map-objects` style matching: `background_image` plus `inpainting`. */
|
|
3969
|
+
supportsMapScene = true;
|
|
3793
3970
|
/**
|
|
3794
3971
|
* `inpaint` (`/inpaint-v3`, a mask) and `image-to-image` (`/edit-images-v2`,
|
|
3795
3972
|
* no mask) both exist on PixelLab, and so do `reduce-colors`
|
|
@@ -3798,7 +3975,9 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
3798
3975
|
* rather than a described edit — and `animate`/`animate-pixminimax`
|
|
3799
3976
|
* (`/animate-with-text-v3`, `/animate-pixminimax`), which animate any loose
|
|
3800
3977
|
* image from a text description with no character/object resource
|
|
3801
|
-
* required —
|
|
3978
|
+
* required — `animate-skeleton` (`/animate-with-skeleton-v3`, posing the
|
|
3979
|
+
* source from a supplied per-frame skeleton instead of a text description)
|
|
3980
|
+
* — and `interpolate` (`/interpolation-v2`, the in-betweens
|
|
3802
3981
|
* from one keyframe to another) and `edit-animation`
|
|
3803
3982
|
* (`/edit-animation-v2`, one text edit applied across a whole frame set).
|
|
3804
3983
|
* `outpaint` does not: there is no canvas-expansion endpoint in the API,
|
|
@@ -3806,7 +3985,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
3806
3985
|
* outpaint path yet.
|
|
3807
3986
|
*/
|
|
3808
3987
|
supportsRevision(mode2) {
|
|
3809
|
-
return mode2 === "inpaint" || mode2 === "image-to-image" || mode2 === "reduce-colors" || mode2 === "correct-pixelart" || mode2 === "animate" || mode2 === "animate-pixminimax" || mode2 === "interpolate" || mode2 === "edit-animation";
|
|
3988
|
+
return mode2 === "inpaint" || mode2 === "image-to-image" || mode2 === "reduce-colors" || mode2 === "correct-pixelart" || mode2 === "animate" || mode2 === "animate-pixminimax" || mode2 === "animate-skeleton" || mode2 === "interpolate" || mode2 === "edit-animation";
|
|
3810
3989
|
}
|
|
3811
3990
|
/** PixelLab's own constraints: submissions must be >2s apart, and
|
|
3812
3991
|
* background jobs in flight are capped by subscription tier (Tier 1=8,
|
|
@@ -3837,6 +4016,10 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
3837
4016
|
if (spec.revision?.mode === "reduce-colors" || spec.revision?.mode === "correct-pixelart") {
|
|
3838
4017
|
return { unit: "generations", amount: 0.1, candidates: 1 };
|
|
3839
4018
|
}
|
|
4019
|
+
if (spec.revision?.mode === "animate-skeleton") {
|
|
4020
|
+
const frames = spec.revision.frames ?? 8;
|
|
4021
|
+
return { unit: "generations", amount: Math.ceil(animateSkeletonCost(frames)), candidates: 1 };
|
|
4022
|
+
}
|
|
3840
4023
|
if (spec.revision?.mode === "interpolate" || spec.revision?.mode === "edit-animation") {
|
|
3841
4024
|
const width = spec.revision.sourceWidth ?? spec.width;
|
|
3842
4025
|
const height = spec.revision.sourceHeight ?? spec.height;
|
|
@@ -3918,6 +4101,18 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
3918
4101
|
throw new Error(`PixelLab correct-pixelart source is ${width}x${height}; the API takes at most 1024 pixels per side`);
|
|
3919
4102
|
}
|
|
3920
4103
|
}
|
|
4104
|
+
if (spec.revision?.mode === "animate-skeleton") {
|
|
4105
|
+
const { sourceWidth: width, sourceHeight: height, frames, skeletonTemplate } = spec.revision;
|
|
4106
|
+
if (width != null && height != null && (width > 256 || height > 256)) {
|
|
4107
|
+
throw new Error(`PixelLab animate-skeleton source is ${width}x${height}; the API takes at most 256 pixels per side`);
|
|
4108
|
+
}
|
|
4109
|
+
if (frames != null && (frames < 3 || frames > 15)) {
|
|
4110
|
+
throw new Error(`PixelLab animate-skeleton takes 3 to 15 frames; the keypoints file has ${frames}`);
|
|
4111
|
+
}
|
|
4112
|
+
if (skeletonTemplate && !CHARACTER_TEMPLATES.includes(skeletonTemplate)) {
|
|
4113
|
+
throw new Error(`PixelLab animate-skeleton template "${skeletonTemplate}" is not one of ${CHARACTER_TEMPLATES.join(", ")}`);
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
3921
4116
|
if (spec.revision?.mode === "animate" || spec.revision?.mode === "animate-pixminimax") {
|
|
3922
4117
|
const { sourceWidth: width, sourceHeight: height, mode: mode2, frames, lastFrameWidth, lastFrameHeight } = spec.revision;
|
|
3923
4118
|
if (width != null && height != null && (width > 256 || height > 256)) {
|
|
@@ -4917,7 +5112,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
4917
5112
|
outline: spec.outline,
|
|
4918
5113
|
shading: spec.shading,
|
|
4919
5114
|
detail: spec.detail,
|
|
4920
|
-
seed: spec.seed
|
|
5115
|
+
seed: spec.seed,
|
|
5116
|
+
scene: spec.scene ? mapScenePayload(spec) : void 0
|
|
4921
5117
|
});
|
|
4922
5118
|
return { jobId: res.object_id, metadata: { backgroundJobId: res.background_job_id } };
|
|
4923
5119
|
}
|
|
@@ -5067,6 +5263,27 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5067
5263
|
});
|
|
5068
5264
|
return { jobId: res2.background_job_id };
|
|
5069
5265
|
}
|
|
5266
|
+
if (revision.mode === "animate-skeleton") {
|
|
5267
|
+
if (!revision.keypointsFile || !revision.keypointsSha256 || !revision.skeleton) {
|
|
5268
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: revision keypoints are not ready`);
|
|
5269
|
+
}
|
|
5270
|
+
const keypointsBytes = (0, import_node_fs2.readFileSync)(revision.keypointsFile);
|
|
5271
|
+
if (sha256(keypointsBytes) !== revision.keypointsSha256) {
|
|
5272
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: revision keypoints changed after the manifest was resolved`);
|
|
5273
|
+
}
|
|
5274
|
+
const res2 = await this.client.animateWithSkeletonV3({
|
|
5275
|
+
firstFrame: image,
|
|
5276
|
+
firstFrameKeypoints: revision.skeleton.firstFrameKeypoints,
|
|
5277
|
+
keypoints: revision.skeleton.frames,
|
|
5278
|
+
direction: revision.direction,
|
|
5279
|
+
templateId: revision.skeletonTemplate,
|
|
5280
|
+
action: spec.prompt,
|
|
5281
|
+
description: revision.description,
|
|
5282
|
+
seed: spec.seed,
|
|
5283
|
+
noBackground: spec.noBackground
|
|
5284
|
+
});
|
|
5285
|
+
return { jobId: res2.background_job_id };
|
|
5286
|
+
}
|
|
5070
5287
|
if (revision.strength != null) {
|
|
5071
5288
|
throw new Error(
|
|
5072
5289
|
`${spec.styleId}/${spec.assetId}: PixelLab image-to-image revisions take no strength; edit-images-v2 always applies the full instruction`
|
|
@@ -5132,7 +5349,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5132
5349
|
if (revisionMode === "reduce-colors" || revisionMode === "correct-pixelart") {
|
|
5133
5350
|
return this.pollCachedRevision(jobId, context);
|
|
5134
5351
|
}
|
|
5135
|
-
if (revisionMode === "animate" || revisionMode === "animate-pixminimax" || revisionMode === "interpolate" || revisionMode === "edit-animation") {
|
|
5352
|
+
if (revisionMode === "animate" || revisionMode === "animate-pixminimax" || revisionMode === "animate-skeleton" || revisionMode === "interpolate" || revisionMode === "edit-animation") {
|
|
5136
5353
|
return this.pollAnimateRevision(jobId, context);
|
|
5137
5354
|
}
|
|
5138
5355
|
if (context?.spec?.revision) return this.pollRevision(jobId);
|
|
@@ -5773,6 +5990,21 @@ function findObjectAnimation(object, name, direction, animationId) {
|
|
|
5773
5990
|
}
|
|
5774
5991
|
return null;
|
|
5775
5992
|
}
|
|
5993
|
+
function mapScenePayload(spec) {
|
|
5994
|
+
const scene = spec.scene;
|
|
5995
|
+
const read = (file, hash, label) => {
|
|
5996
|
+
const bytes = (0, import_node_fs2.readFileSync)(file);
|
|
5997
|
+
if (!hash || sha256(bytes) !== hash) {
|
|
5998
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: ${label} changed after the manifest was resolved`);
|
|
5999
|
+
}
|
|
6000
|
+
return { base64: bytes.toString("base64"), format: "png" };
|
|
6001
|
+
};
|
|
6002
|
+
const placement = scene.placement;
|
|
6003
|
+
return {
|
|
6004
|
+
image: read(scene.file, scene.sha256, "scene image"),
|
|
6005
|
+
placement: placement.type === "mask" ? { type: "mask", mask: read(placement.file, placement.sha256, "scene mask") } : placement
|
|
6006
|
+
};
|
|
6007
|
+
}
|
|
5776
6008
|
|
|
5777
6009
|
// src/providers/retrodiffusion.ts
|
|
5778
6010
|
var DEFAULT_BASE_URL = "https://api.retrodiffusion.ai/v1";
|
|
@@ -6867,11 +7099,12 @@ var ComfyUIProvider = class _ComfyUIProvider {
|
|
|
6867
7099
|
/**
|
|
6868
7100
|
* Everything else resolves generically to whatever the user's own
|
|
6869
7101
|
* workflow does with `bindings.sourceImage`. The frame-set modes
|
|
6870
|
-
* (`animate`, `animate-pixminimax`, `
|
|
6871
|
-
* the exception: they produce an ordered frame set,
|
|
6872
|
-
* revision path always writes a single output image
|
|
6873
|
-
* below) — a real structural gap, not a missing
|
|
6874
|
-
* rejected here rather than only failing once
|
|
7102
|
+
* (`animate`, `animate-pixminimax`, `animate-skeleton`, `interpolate`,
|
|
7103
|
+
* `edit-animation`) are the exception: they produce an ordered frame set,
|
|
7104
|
+
* and this adapter's revision path always writes a single output image
|
|
7105
|
+
* (see `submit`/`fetch` below) — a real structural gap, not a missing
|
|
7106
|
+
* binding, so they are rejected here rather than only failing once
|
|
7107
|
+
* `validate` runs.
|
|
6875
7108
|
*/
|
|
6876
7109
|
supportsRevision(mode2) {
|
|
6877
7110
|
return !FRAME_SET_REVISION_MODES.includes(mode2);
|
|
@@ -7551,6 +7784,7 @@ var FakeProvider = class {
|
|
|
7551
7784
|
supports(generator) {
|
|
7552
7785
|
return generator === "1dir" || generator === "map" || generator === "character";
|
|
7553
7786
|
}
|
|
7787
|
+
supportsMapScene = true;
|
|
7554
7788
|
supportsRevision(_mode) {
|
|
7555
7789
|
return true;
|
|
7556
7790
|
}
|
|
@@ -8774,6 +9008,8 @@ async function resolveSpecs(loaded, filter) {
|
|
|
8774
9008
|
const paletteImage = paletteImageFile ? await optionalRevisionImage(paletteImageFile, "revision palette image", "png") : null;
|
|
8775
9009
|
const lastFrameFile = asset.revision.lastFrame ? import_node_path5.default.resolve(root, asset.revision.lastFrame) : void 0;
|
|
8776
9010
|
const lastFrame = lastFrameFile ? await optionalRevisionImage(lastFrameFile, "revision last frame") : null;
|
|
9011
|
+
const keypointsFile = asset.revision.keypointsFile ? import_node_path5.default.resolve(root, asset.revision.keypointsFile) : void 0;
|
|
9012
|
+
const keypoints = keypointsFile ? await optionalSkeletonSet(keypointsFile) : null;
|
|
8777
9013
|
resolved.revision = {
|
|
8778
9014
|
mode: asset.revision.mode,
|
|
8779
9015
|
sourceAssetId: asset.revision.from,
|
|
@@ -8814,6 +9050,18 @@ async function resolveSpecs(loaded, filter) {
|
|
|
8814
9050
|
} : {},
|
|
8815
9051
|
...asset.revision.direction ? { direction: asset.revision.direction } : {},
|
|
8816
9052
|
...asset.revision.enhancePrompt == null ? {} : { enhancePrompt: asset.revision.enhancePrompt },
|
|
9053
|
+
...keypointsFile ? {
|
|
9054
|
+
keypointsFile,
|
|
9055
|
+
keypointsSha256: keypoints?.hash ?? null,
|
|
9056
|
+
skeleton: keypoints?.skeleton ?? null,
|
|
9057
|
+
// The manifest's own `frames` field stays rejected for this
|
|
9058
|
+
// mode (superRefine, types.ts) — the real frame count comes
|
|
9059
|
+
// from the keypoints file once it exists, not a manifest
|
|
9060
|
+
// number, so plan can only know it once authored.
|
|
9061
|
+
...keypoints ? { frames: keypoints.skeleton.frames.length } : {}
|
|
9062
|
+
} : {},
|
|
9063
|
+
...asset.revision.skeletonTemplate ? { skeletonTemplate: asset.revision.skeletonTemplate } : {},
|
|
9064
|
+
...asset.revision.description ? { description: asset.revision.description } : {},
|
|
8817
9065
|
...asset.revision.engine ? { engine: asset.revision.engine } : {}
|
|
8818
9066
|
};
|
|
8819
9067
|
}
|
|
@@ -8867,6 +9115,7 @@ async function resolveSpecs(loaded, filter) {
|
|
|
8867
9115
|
};
|
|
8868
9116
|
}
|
|
8869
9117
|
}
|
|
9118
|
+
if (asset.scene) resolved.scene = await resolveMapScene(root, styleId, assetId, resolved.generator, asset.scene, activeProvider);
|
|
8870
9119
|
resolved.specHash = specHash(
|
|
8871
9120
|
resolved,
|
|
8872
9121
|
styleImageHashes,
|
|
@@ -8925,6 +9174,32 @@ function pngPath(file) {
|
|
|
8925
9174
|
const extension = import_node_path5.default.extname(file);
|
|
8926
9175
|
return extension ? `${file.slice(0, -extension.length)}.png` : `${file}.png`;
|
|
8927
9176
|
}
|
|
9177
|
+
async function resolveMapScene(root, styleId, assetId, generator, scene, provider) {
|
|
9178
|
+
if (generator !== "map") {
|
|
9179
|
+
throw new Error(`assets.${assetId}.scene: only a map object can be drawn into a scene; style "${styleId}" uses "${generator}"`);
|
|
9180
|
+
}
|
|
9181
|
+
if (!provider.supportsMapScene) {
|
|
9182
|
+
throw new Error(`assets.${assetId}.scene: provider "${provider.id}" cannot draw into a scene; PixelLab's /map-objects can`);
|
|
9183
|
+
}
|
|
9184
|
+
const file = import_node_path5.default.resolve(root, scene.image);
|
|
9185
|
+
const image = await optionalRevisionImage(file, "scene image", "png");
|
|
9186
|
+
const base = { file, sha256: image?.hash ?? null, width: image?.width ?? null, height: image?.height ?? null };
|
|
9187
|
+
const placement = scene.placement;
|
|
9188
|
+
if ("mask" in placement) {
|
|
9189
|
+
const maskFile = import_node_path5.default.resolve(root, placement.mask);
|
|
9190
|
+
const mask = await optionalRevisionImage(maskFile, "scene mask", "png");
|
|
9191
|
+
if (image && mask && (image.width !== mask.width || image.height !== mask.height)) {
|
|
9192
|
+
throw new Error(
|
|
9193
|
+
`assets.${assetId}.scene: the mask is ${mask.width}x${mask.height}; the scene ${scene.image} is ${image.width}x${image.height}`
|
|
9194
|
+
);
|
|
9195
|
+
}
|
|
9196
|
+
return {
|
|
9197
|
+
...base,
|
|
9198
|
+
placement: { type: "mask", file: maskFile, sha256: mask?.hash ?? null, width: mask?.width ?? null, height: mask?.height ?? null }
|
|
9199
|
+
};
|
|
9200
|
+
}
|
|
9201
|
+
return "oval" in placement ? { ...base, placement: { type: "oval", fraction: placement.oval } } : { ...base, placement: { type: "rectangle", fraction: placement.rectangle } };
|
|
9202
|
+
}
|
|
8928
9203
|
async function optionalRevisionImage(file, label, requiredFormat) {
|
|
8929
9204
|
if (!(0, import_node_fs5.existsSync)(file)) return null;
|
|
8930
9205
|
const bytes = await (0, import_promises3.readFile)(file);
|
|
@@ -8935,6 +9210,17 @@ async function optionalRevisionImage(file, label, requiredFormat) {
|
|
|
8935
9210
|
}
|
|
8936
9211
|
return { hash: sha256(bytes), ...metadata };
|
|
8937
9212
|
}
|
|
9213
|
+
async function optionalSkeletonSet(file) {
|
|
9214
|
+
if (!(0, import_node_fs5.existsSync)(file)) return null;
|
|
9215
|
+
const bytes = await (0, import_promises3.readFile)(file);
|
|
9216
|
+
let json;
|
|
9217
|
+
try {
|
|
9218
|
+
json = JSON.parse(bytes.toString("utf8"));
|
|
9219
|
+
} catch (error) {
|
|
9220
|
+
throw new Error(`revision keypoints file ${file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
9221
|
+
}
|
|
9222
|
+
return { hash: sha256(bytes), skeleton: parseSkeletonSet(json, file) };
|
|
9223
|
+
}
|
|
8938
9224
|
async function revisionSourceMembers(stem, label) {
|
|
8939
9225
|
if ((0, import_node_fs5.existsSync)(stem)) return null;
|
|
8940
9226
|
const at = (role) => memberPath(stem, role, 0, 2, MediaType.PNG);
|
|
@@ -10584,6 +10870,7 @@ async function inspectRevisionReadiness(spec, lock) {
|
|
|
10584
10870
|
if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
|
|
10585
10871
|
if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
|
|
10586
10872
|
if (spec.objectPro?.parentSpec) return inspectObjectProParent(spec, lock, /* @__PURE__ */ new Set());
|
|
10873
|
+
if (spec.scene) return inspectScene(spec);
|
|
10587
10874
|
if (!spec.revision) return null;
|
|
10588
10875
|
return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
|
|
10589
10876
|
}
|
|
@@ -10601,6 +10888,16 @@ async function inspectStyleAnchor(spec, lock, seen) {
|
|
|
10601
10888
|
}
|
|
10602
10889
|
return { ready: true, reason: `${label} is current` };
|
|
10603
10890
|
}
|
|
10891
|
+
async function inspectScene(spec) {
|
|
10892
|
+
const scene = spec.scene;
|
|
10893
|
+
const files = [{ label: "scene image", file: scene.file, sha256: scene.sha256 }];
|
|
10894
|
+
if (scene.placement.type === "mask") files.push({ label: "scene mask", file: scene.placement.file, sha256: scene.placement.sha256 });
|
|
10895
|
+
for (const { label, file, sha256: sha2562 } of files) {
|
|
10896
|
+
if (!sha2562 || !(0, import_node_fs8.existsSync)(file)) return { ready: false, reason: `${label} does not exist yet: ${file}` };
|
|
10897
|
+
if (await sha256File(file) !== sha2562) return { ready: false, reason: `${label} changed after the manifest was resolved` };
|
|
10898
|
+
}
|
|
10899
|
+
return { ready: true, reason: "scene is current" };
|
|
10900
|
+
}
|
|
10604
10901
|
async function inspectMirror(spec, lock, seen) {
|
|
10605
10902
|
const source = spec.mirror.sourceSpec;
|
|
10606
10903
|
const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
|
|
@@ -11057,47 +11354,47 @@ var import_node_path14 = __toESM(require("path"), 1);
|
|
|
11057
11354
|
var import_node_fs10 = require("fs");
|
|
11058
11355
|
var import_promises7 = require("fs/promises");
|
|
11059
11356
|
var import_node_url = require("url");
|
|
11060
|
-
var
|
|
11357
|
+
var import_zod4 = require("zod");
|
|
11061
11358
|
var SHA256_RE = /^[0-9a-f]{64}$/;
|
|
11062
11359
|
var RECIPE_ID_RE = /^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/;
|
|
11063
11360
|
var VERSION_RE = /^\d+\.\d+\.\d+$/;
|
|
11064
11361
|
var RECIPE_FILE = "pixelkiln.recipe.json";
|
|
11065
11362
|
var RECIPE_DIR_TOKEN = "{{recipeDir}}";
|
|
11066
|
-
var PortablePathSchema =
|
|
11363
|
+
var PortablePathSchema = import_zod4.z.string().min(1).refine((value) => {
|
|
11067
11364
|
if (value.includes("\\") || import_node_path14.default.posix.isAbsolute(value)) return false;
|
|
11068
11365
|
const parts = value.split("/");
|
|
11069
11366
|
return !parts.includes("") && !parts.includes(".") && !parts.includes("..");
|
|
11070
11367
|
}, "expected a portable relative path without '.', '..', or backslashes");
|
|
11071
|
-
var RecipeBindingSchema =
|
|
11072
|
-
nodeId:
|
|
11073
|
-
input:
|
|
11368
|
+
var RecipeBindingSchema = import_zod4.z.object({
|
|
11369
|
+
nodeId: import_zod4.z.string().min(1),
|
|
11370
|
+
input: import_zod4.z.string().min(1)
|
|
11074
11371
|
}).strict();
|
|
11075
|
-
var RecipeSchema =
|
|
11076
|
-
$schema:
|
|
11077
|
-
format:
|
|
11078
|
-
schemaVersion:
|
|
11079
|
-
id:
|
|
11080
|
-
version:
|
|
11081
|
-
provider:
|
|
11082
|
-
summary:
|
|
11083
|
-
files:
|
|
11372
|
+
var RecipeSchema = import_zod4.z.object({
|
|
11373
|
+
$schema: import_zod4.z.string().url().optional(),
|
|
11374
|
+
format: import_zod4.z.literal("pixelkiln-recipe"),
|
|
11375
|
+
schemaVersion: import_zod4.z.literal(1),
|
|
11376
|
+
id: import_zod4.z.string().regex(RECIPE_ID_RE, "expected provider/name"),
|
|
11377
|
+
version: import_zod4.z.string().regex(VERSION_RE, "expected x.y.z"),
|
|
11378
|
+
provider: import_zod4.z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
11379
|
+
summary: import_zod4.z.string().min(1).max(240),
|
|
11380
|
+
files: import_zod4.z.array(import_zod4.z.object({
|
|
11084
11381
|
path: PortablePathSchema,
|
|
11085
|
-
role:
|
|
11086
|
-
sha256:
|
|
11382
|
+
role: import_zod4.z.enum(["workflow", "reference"]),
|
|
11383
|
+
sha256: import_zod4.z.string().regex(SHA256_RE)
|
|
11087
11384
|
}).strict()).default([]),
|
|
11088
|
-
models:
|
|
11385
|
+
models: import_zod4.z.array(import_zod4.z.object({
|
|
11089
11386
|
path: PortablePathSchema,
|
|
11090
|
-
sha256:
|
|
11091
|
-
source:
|
|
11092
|
-
license:
|
|
11387
|
+
sha256: import_zod4.z.string().regex(SHA256_RE),
|
|
11388
|
+
source: import_zod4.z.string().url(),
|
|
11389
|
+
license: import_zod4.z.string().min(1)
|
|
11093
11390
|
}).strict()).default([]),
|
|
11094
|
-
styleId:
|
|
11391
|
+
styleId: import_zod4.z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
11095
11392
|
style: StyleSchema,
|
|
11096
|
-
workflow:
|
|
11393
|
+
workflow: import_zod4.z.object({
|
|
11097
11394
|
path: PortablePathSchema,
|
|
11098
|
-
outputNodeId:
|
|
11099
|
-
numImages:
|
|
11100
|
-
bindings:
|
|
11395
|
+
outputNodeId: import_zod4.z.string().min(1),
|
|
11396
|
+
numImages: import_zod4.z.number().int().min(1).max(16),
|
|
11397
|
+
bindings: import_zod4.z.object({
|
|
11101
11398
|
prompt: RecipeBindingSchema,
|
|
11102
11399
|
width: RecipeBindingSchema.optional(),
|
|
11103
11400
|
height: RecipeBindingSchema.optional(),
|
|
@@ -11108,67 +11405,67 @@ var RecipeSchema = import_zod3.z.object({
|
|
|
11108
11405
|
strength: RecipeBindingSchema.optional()
|
|
11109
11406
|
}).strict()
|
|
11110
11407
|
}).strict().optional(),
|
|
11111
|
-
quality:
|
|
11112
|
-
stage:
|
|
11113
|
-
workingCanvas:
|
|
11114
|
-
width:
|
|
11115
|
-
height:
|
|
11408
|
+
quality: import_zod4.z.object({
|
|
11409
|
+
stage: import_zod4.z.enum(["composition-source", "production-candidate"]),
|
|
11410
|
+
workingCanvas: import_zod4.z.object({
|
|
11411
|
+
width: import_zod4.z.number().int().min(16),
|
|
11412
|
+
height: import_zod4.z.number().int().min(16)
|
|
11116
11413
|
}).strict(),
|
|
11117
|
-
recommendedNativeSize:
|
|
11118
|
-
min:
|
|
11119
|
-
max:
|
|
11414
|
+
recommendedNativeSize: import_zod4.z.object({
|
|
11415
|
+
min: import_zod4.z.number().int().min(1),
|
|
11416
|
+
max: import_zod4.z.number().int().min(1)
|
|
11120
11417
|
}).strict(),
|
|
11121
|
-
paletteColors:
|
|
11122
|
-
min:
|
|
11123
|
-
max:
|
|
11418
|
+
paletteColors: import_zod4.z.object({
|
|
11419
|
+
min: import_zod4.z.number().int().min(1),
|
|
11420
|
+
max: import_zod4.z.number().int().min(1)
|
|
11124
11421
|
}).strict(),
|
|
11125
|
-
background:
|
|
11126
|
-
checks:
|
|
11422
|
+
background: import_zod4.z.enum(["opaque", "transparent", "full-bleed"]),
|
|
11423
|
+
checks: import_zod4.z.array(import_zod4.z.enum([
|
|
11127
11424
|
"prompt-coverage",
|
|
11128
11425
|
"native-grid",
|
|
11129
11426
|
"final-palette",
|
|
11130
11427
|
"alpha-edge",
|
|
11131
11428
|
"human-1x"
|
|
11132
11429
|
])).min(1),
|
|
11133
|
-
notes:
|
|
11430
|
+
notes: import_zod4.z.array(import_zod4.z.string().min(1)).default([])
|
|
11134
11431
|
}).strict(),
|
|
11135
|
-
integrity:
|
|
11136
|
-
algorithm:
|
|
11137
|
-
digest:
|
|
11432
|
+
integrity: import_zod4.z.object({
|
|
11433
|
+
algorithm: import_zod4.z.literal("sha256"),
|
|
11434
|
+
digest: import_zod4.z.string().regex(SHA256_RE)
|
|
11138
11435
|
}).strict()
|
|
11139
11436
|
}).strict().superRefine((recipe, context) => {
|
|
11140
11437
|
if (recipe.style.provider && recipe.style.provider !== recipe.provider) {
|
|
11141
11438
|
context.addIssue({
|
|
11142
|
-
code:
|
|
11439
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11143
11440
|
path: ["style", "provider"],
|
|
11144
11441
|
message: "must match the recipe provider"
|
|
11145
11442
|
});
|
|
11146
11443
|
}
|
|
11147
11444
|
const filePaths = recipe.files.map((file) => file.path);
|
|
11148
11445
|
if (new Set(filePaths).size !== filePaths.length) {
|
|
11149
|
-
context.addIssue({ code:
|
|
11446
|
+
context.addIssue({ code: import_zod4.z.ZodIssueCode.custom, path: ["files"], message: "duplicate file path" });
|
|
11150
11447
|
}
|
|
11151
11448
|
const modelPaths = recipe.models.map((model) => model.path);
|
|
11152
11449
|
if (new Set(modelPaths).size !== modelPaths.length) {
|
|
11153
|
-
context.addIssue({ code:
|
|
11450
|
+
context.addIssue({ code: import_zod4.z.ZodIssueCode.custom, path: ["models"], message: "duplicate model path" });
|
|
11154
11451
|
}
|
|
11155
11452
|
if (filePaths.includes(RECIPE_FILE)) {
|
|
11156
11453
|
context.addIssue({
|
|
11157
|
-
code:
|
|
11454
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11158
11455
|
path: ["files"],
|
|
11159
11456
|
message: `${RECIPE_FILE} cannot hash itself`
|
|
11160
11457
|
});
|
|
11161
11458
|
}
|
|
11162
11459
|
if (recipe.quality.recommendedNativeSize.min > recipe.quality.recommendedNativeSize.max) {
|
|
11163
11460
|
context.addIssue({
|
|
11164
|
-
code:
|
|
11461
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11165
11462
|
path: ["quality", "recommendedNativeSize"],
|
|
11166
11463
|
message: "min cannot exceed max"
|
|
11167
11464
|
});
|
|
11168
11465
|
}
|
|
11169
11466
|
if (recipe.quality.paletteColors.min > recipe.quality.paletteColors.max) {
|
|
11170
11467
|
context.addIssue({
|
|
11171
|
-
code:
|
|
11468
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11172
11469
|
path: ["quality", "paletteColors"],
|
|
11173
11470
|
message: "min cannot exceed max"
|
|
11174
11471
|
});
|
|
@@ -11177,7 +11474,7 @@ var RecipeSchema = import_zod3.z.object({
|
|
|
11177
11474
|
(file) => file.path === recipe.workflow.path && file.role === "workflow"
|
|
11178
11475
|
)) {
|
|
11179
11476
|
context.addIssue({
|
|
11180
|
-
code:
|
|
11477
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11181
11478
|
path: ["workflow", "path"],
|
|
11182
11479
|
message: "must name a file whose role is workflow"
|
|
11183
11480
|
});
|
|
@@ -11185,7 +11482,7 @@ var RecipeSchema = import_zod3.z.object({
|
|
|
11185
11482
|
if (recipe.provider === "comfyui") {
|
|
11186
11483
|
if (!recipe.workflow) {
|
|
11187
11484
|
context.addIssue({
|
|
11188
|
-
code:
|
|
11485
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11189
11486
|
path: ["workflow"],
|
|
11190
11487
|
message: "ComfyUI recipes require workflow metadata"
|
|
11191
11488
|
});
|
|
@@ -11194,7 +11491,7 @@ var RecipeSchema = import_zod3.z.object({
|
|
|
11194
11491
|
const options = recipe.style.providerOptions.comfyui;
|
|
11195
11492
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
11196
11493
|
context.addIssue({
|
|
11197
|
-
code:
|
|
11494
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11198
11495
|
path: ["style", "providerOptions", "comfyui"],
|
|
11199
11496
|
message: "ComfyUI recipes require ComfyUI provider options"
|
|
11200
11497
|
});
|
|
@@ -11208,7 +11505,7 @@ var RecipeSchema = import_zod3.z.object({
|
|
|
11208
11505
|
};
|
|
11209
11506
|
if (JSON.stringify(canonical3(options)) !== JSON.stringify(canonical3(expected))) {
|
|
11210
11507
|
context.addIssue({
|
|
11211
|
-
code:
|
|
11508
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
11212
11509
|
path: ["style", "providerOptions", "comfyui"],
|
|
11213
11510
|
message: "must match workflow metadata and use {{recipeDir}} for workflowFile"
|
|
11214
11511
|
});
|
|
@@ -11646,11 +11943,11 @@ async function generateFont(client2, opts) {
|
|
|
11646
11943
|
var import_node_path17 = __toESM(require("path"), 1);
|
|
11647
11944
|
var import_node_fs13 = require("fs");
|
|
11648
11945
|
var import_promises10 = require("fs/promises");
|
|
11649
|
-
var
|
|
11946
|
+
var import_zod5 = require("zod");
|
|
11650
11947
|
var SHA256_RE2 = /^[0-9a-f]{64}$/;
|
|
11651
11948
|
var HEX_RE = /^#[0-9a-f]{6}$/;
|
|
11652
11949
|
var MAX_REDMEAN_DISTANCE = 765;
|
|
11653
|
-
var QualityPathSchema =
|
|
11950
|
+
var QualityPathSchema = import_zod5.z.string().min(1).refine(
|
|
11654
11951
|
(value) => !import_node_path17.default.posix.isAbsolute(value) && !value.includes("\\"),
|
|
11655
11952
|
"expected a portable relative path"
|
|
11656
11953
|
);
|
|
@@ -11664,53 +11961,53 @@ var DEFAULT_QUALITY_TOLERANCES = {
|
|
|
11664
11961
|
maxEdgeContrastDrop: 0.03,
|
|
11665
11962
|
maxIsolatedPixelIncrease: 5e-3
|
|
11666
11963
|
};
|
|
11667
|
-
var QualityToleranceSchema =
|
|
11668
|
-
requireExactHash:
|
|
11669
|
-
maxColorCountIncrease:
|
|
11670
|
-
maxNewColors:
|
|
11671
|
-
maxTransparencyDelta:
|
|
11672
|
-
maxPartialAlphaIncrease:
|
|
11673
|
-
maxEdgeDensityDelta:
|
|
11674
|
-
maxEdgeContrastDrop:
|
|
11675
|
-
maxIsolatedPixelIncrease:
|
|
11964
|
+
var QualityToleranceSchema = import_zod5.z.object({
|
|
11965
|
+
requireExactHash: import_zod5.z.boolean(),
|
|
11966
|
+
maxColorCountIncrease: import_zod5.z.number().int().min(0),
|
|
11967
|
+
maxNewColors: import_zod5.z.number().int().min(0),
|
|
11968
|
+
maxTransparencyDelta: import_zod5.z.number().min(0).max(1),
|
|
11969
|
+
maxPartialAlphaIncrease: import_zod5.z.number().min(0).max(1),
|
|
11970
|
+
maxEdgeDensityDelta: import_zod5.z.number().min(0).max(1),
|
|
11971
|
+
maxEdgeContrastDrop: import_zod5.z.number().min(0).max(1),
|
|
11972
|
+
maxIsolatedPixelIncrease: import_zod5.z.number().min(0).max(1)
|
|
11676
11973
|
}).strict();
|
|
11677
|
-
var ImageQualityMetricsSchema =
|
|
11678
|
-
sha256:
|
|
11679
|
-
width:
|
|
11680
|
-
height:
|
|
11681
|
-
colorCount:
|
|
11682
|
-
colors:
|
|
11683
|
-
transparency:
|
|
11684
|
-
partialAlpha:
|
|
11685
|
-
edgeDensity:
|
|
11686
|
-
meanEdgeContrast:
|
|
11687
|
-
isolatedPixelRatio:
|
|
11974
|
+
var ImageQualityMetricsSchema = import_zod5.z.object({
|
|
11975
|
+
sha256: import_zod5.z.string().regex(SHA256_RE2),
|
|
11976
|
+
width: import_zod5.z.number().int().min(1),
|
|
11977
|
+
height: import_zod5.z.number().int().min(1),
|
|
11978
|
+
colorCount: import_zod5.z.number().int().min(0),
|
|
11979
|
+
colors: import_zod5.z.array(import_zod5.z.string().regex(HEX_RE)),
|
|
11980
|
+
transparency: import_zod5.z.number().min(0).max(1),
|
|
11981
|
+
partialAlpha: import_zod5.z.number().min(0).max(1),
|
|
11982
|
+
edgeDensity: import_zod5.z.number().min(0).max(1),
|
|
11983
|
+
meanEdgeContrast: import_zod5.z.number().min(0).max(1),
|
|
11984
|
+
isolatedPixelRatio: import_zod5.z.number().min(0).max(1)
|
|
11688
11985
|
}).strict();
|
|
11689
|
-
var QualityBaselineCaseSchema =
|
|
11690
|
-
id:
|
|
11986
|
+
var QualityBaselineCaseSchema = import_zod5.z.object({
|
|
11987
|
+
id: import_zod5.z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),
|
|
11691
11988
|
file: QualityPathSchema,
|
|
11692
|
-
record:
|
|
11989
|
+
record: import_zod5.z.object({
|
|
11693
11990
|
path: QualityPathSchema,
|
|
11694
|
-
sha256:
|
|
11991
|
+
sha256: import_zod5.z.string().regex(SHA256_RE2)
|
|
11695
11992
|
}).strict().optional(),
|
|
11696
11993
|
expected: ImageQualityMetricsSchema,
|
|
11697
11994
|
tolerances: QualityToleranceSchema
|
|
11698
11995
|
}).strict();
|
|
11699
|
-
var QualityBaselineSchema =
|
|
11700
|
-
$schema:
|
|
11701
|
-
format:
|
|
11702
|
-
schemaVersion:
|
|
11703
|
-
cases:
|
|
11996
|
+
var QualityBaselineSchema = import_zod5.z.object({
|
|
11997
|
+
$schema: import_zod5.z.string().url().optional(),
|
|
11998
|
+
format: import_zod5.z.literal("pixelkiln-quality-baseline"),
|
|
11999
|
+
schemaVersion: import_zod5.z.literal(1),
|
|
12000
|
+
cases: import_zod5.z.array(QualityBaselineCaseSchema).min(1)
|
|
11704
12001
|
}).strict().superRefine((baseline, context) => {
|
|
11705
12002
|
const ids = baseline.cases.map((entry) => entry.id);
|
|
11706
12003
|
if (new Set(ids).size !== ids.length) {
|
|
11707
|
-
context.addIssue({ code:
|
|
12004
|
+
context.addIssue({ code: import_zod5.z.ZodIssueCode.custom, path: ["cases"], message: "duplicate case id" });
|
|
11708
12005
|
}
|
|
11709
12006
|
});
|
|
11710
|
-
var QualityInputSchema =
|
|
11711
|
-
id:
|
|
11712
|
-
path:
|
|
11713
|
-
record:
|
|
12007
|
+
var QualityInputSchema = import_zod5.z.object({
|
|
12008
|
+
id: import_zod5.z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),
|
|
12009
|
+
path: import_zod5.z.string().min(1),
|
|
12010
|
+
record: import_zod5.z.string().min(1).optional(),
|
|
11714
12011
|
tolerances: QualityToleranceSchema.partial().optional()
|
|
11715
12012
|
}).strict();
|
|
11716
12013
|
function message4(error) {
|
|
@@ -11812,7 +12109,7 @@ async function measureImageQuality(file) {
|
|
|
11812
12109
|
}
|
|
11813
12110
|
}
|
|
11814
12111
|
function resolveQualityInputs(raw, inputsFilePath) {
|
|
11815
|
-
const parsed =
|
|
12112
|
+
const parsed = import_zod5.z.array(QualityInputSchema).min(1).safeParse(raw);
|
|
11816
12113
|
if (!parsed.success) {
|
|
11817
12114
|
throw new Error(
|
|
11818
12115
|
"--inputs must be a non-empty JSON array of quality cases:\n" + parsed.error.issues.map((issue) => ` ${issue.path.join(".") || "$"}: ${issue.message}`).join("\n")
|
|
@@ -12035,11 +12332,11 @@ var import_node_path21 = __toESM(require("path"), 1);
|
|
|
12035
12332
|
var import_promises11 = require("fs/promises");
|
|
12036
12333
|
var import_node_fs14 = require("fs");
|
|
12037
12334
|
var import_node_path18 = __toESM(require("path"), 1);
|
|
12038
|
-
var
|
|
12039
|
-
var HashCacheSchema =
|
|
12040
|
-
version:
|
|
12335
|
+
var import_zod6 = require("zod");
|
|
12336
|
+
var HashCacheSchema = import_zod6.z.object({
|
|
12337
|
+
version: import_zod6.z.literal(1),
|
|
12041
12338
|
/** objectId → sha256 of that object's image bytes. */
|
|
12042
|
-
hashes:
|
|
12339
|
+
hashes: import_zod6.z.record(import_zod6.z.string())
|
|
12043
12340
|
});
|
|
12044
12341
|
var SHA256_HEX = /^[a-f0-9]{64}$/;
|
|
12045
12342
|
function isSha256Hash(value) {
|
|
@@ -13587,6 +13884,9 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
|
|
|
13587
13884
|
...spec.revision.lastFrameSha256 ? { lastFrameSha256: spec.revision.lastFrameSha256 } : {},
|
|
13588
13885
|
...spec.revision.direction ? { direction: spec.revision.direction } : {},
|
|
13589
13886
|
...spec.revision.enhancePrompt == null ? {} : { enhancePrompt: spec.revision.enhancePrompt },
|
|
13887
|
+
...spec.revision.keypointsSha256 ? { keypointsSha256: spec.revision.keypointsSha256 } : {},
|
|
13888
|
+
...spec.revision.skeletonTemplate ? { skeletonTemplate: spec.revision.skeletonTemplate } : {},
|
|
13889
|
+
...spec.revision.description ? { description: spec.revision.description } : {},
|
|
13590
13890
|
...spec.revision.engine ? { engine: spec.revision.engine } : {}
|
|
13591
13891
|
} : null,
|
|
13592
13892
|
outfit: spec.character?.kind === "outfit" && outfitParentEntry ? {
|
|
@@ -14884,20 +15184,20 @@ var import_node_path30 = __toESM(require("path"), 1);
|
|
|
14884
15184
|
var import_promises19 = require("fs/promises");
|
|
14885
15185
|
var import_node_fs23 = require("fs");
|
|
14886
15186
|
var import_node_path26 = __toESM(require("path"), 1);
|
|
14887
|
-
var
|
|
14888
|
-
var WorkspaceProjectSchema =
|
|
14889
|
-
id:
|
|
15187
|
+
var import_zod7 = require("zod");
|
|
15188
|
+
var WorkspaceProjectSchema = import_zod7.z.object({
|
|
15189
|
+
id: import_zod7.z.string().min(1),
|
|
14890
15190
|
/** Manifest path, relative to the catalog file's own directory. */
|
|
14891
|
-
manifest:
|
|
15191
|
+
manifest: import_zod7.z.string().min(1),
|
|
14892
15192
|
/** Lockfile path, relative to the catalog file's own directory. */
|
|
14893
|
-
lock:
|
|
14894
|
-
provider:
|
|
15193
|
+
lock: import_zod7.z.string().min(1),
|
|
15194
|
+
provider: import_zod7.z.string().min(1).default("pixellab"),
|
|
14895
15195
|
/** Free-form label for a shared account, e.g. distinguishing sandboxes. */
|
|
14896
|
-
account:
|
|
15196
|
+
account: import_zod7.z.string().optional()
|
|
14897
15197
|
}).strict();
|
|
14898
|
-
var WorkspaceSchema =
|
|
14899
|
-
version:
|
|
14900
|
-
projects:
|
|
15198
|
+
var WorkspaceSchema = import_zod7.z.object({
|
|
15199
|
+
version: import_zod7.z.literal(1),
|
|
15200
|
+
projects: import_zod7.z.array(WorkspaceProjectSchema).default([])
|
|
14901
15201
|
}).strict();
|
|
14902
15202
|
function parseWorkspace(raw) {
|
|
14903
15203
|
const parsed = WorkspaceSchema.safeParse(raw);
|
|
@@ -15015,62 +15315,62 @@ function validateWorkspace(ws, dir) {
|
|
|
15015
15315
|
|
|
15016
15316
|
// src/gallery/edit.ts
|
|
15017
15317
|
var import_node_path29 = __toESM(require("path"), 1);
|
|
15018
|
-
var
|
|
15318
|
+
var import_zod10 = require("zod");
|
|
15019
15319
|
|
|
15020
15320
|
// src/manifest-edit.ts
|
|
15021
15321
|
var import_promises20 = require("fs/promises");
|
|
15022
15322
|
var import_node_path27 = __toESM(require("path"), 1);
|
|
15023
|
-
var
|
|
15024
|
-
var HexSha =
|
|
15025
|
-
var AssetPatchSchema =
|
|
15026
|
-
prompt:
|
|
15323
|
+
var import_zod8 = require("zod");
|
|
15324
|
+
var HexSha = import_zod8.z.string().regex(/^[0-9a-f]{64}$/);
|
|
15325
|
+
var AssetPatchSchema = import_zod8.z.object({
|
|
15326
|
+
prompt: import_zod8.z.string().optional(),
|
|
15027
15327
|
/** Per-style override for the style being viewed; null removes it. */
|
|
15028
|
-
promptForStyle:
|
|
15029
|
-
category:
|
|
15030
|
-
width:
|
|
15031
|
-
height:
|
|
15032
|
-
size:
|
|
15033
|
-
tags:
|
|
15328
|
+
promptForStyle: import_zod8.z.object({ styleId: import_zod8.z.string().min(1), prompt: import_zod8.z.string().nullable() }).optional(),
|
|
15329
|
+
category: import_zod8.z.string().nullable().optional(),
|
|
15330
|
+
width: import_zod8.z.number().int().nullable().optional(),
|
|
15331
|
+
height: import_zod8.z.number().int().nullable().optional(),
|
|
15332
|
+
size: import_zod8.z.number().int().nullable().optional(),
|
|
15333
|
+
tags: import_zod8.z.array(import_zod8.z.string()).optional()
|
|
15034
15334
|
}).strict();
|
|
15035
|
-
var NewStateSchema =
|
|
15335
|
+
var NewStateSchema = import_zod8.z.object({
|
|
15036
15336
|
/** Asset id of the parent this states; must already exist. */
|
|
15037
|
-
of:
|
|
15038
|
-
paletteFromReference:
|
|
15039
|
-
canvas:
|
|
15337
|
+
of: import_zod8.z.string().min(1),
|
|
15338
|
+
paletteFromReference: import_zod8.z.boolean().optional(),
|
|
15339
|
+
canvas: import_zod8.z.object({ width: import_zod8.z.number().int().min(16).max(256), height: import_zod8.z.number().int().min(16).max(256) }).strict().optional()
|
|
15040
15340
|
}).strict();
|
|
15041
|
-
var NewAnimationSchema =
|
|
15341
|
+
var NewAnimationSchema = import_zod8.z.object({
|
|
15042
15342
|
/** Asset id of the parent this animates; must already exist. */
|
|
15043
|
-
of:
|
|
15343
|
+
of: import_zod8.z.string().min(1),
|
|
15044
15344
|
/** A PixelLab template id (`character` only; `objectPro` has no template concept). */
|
|
15045
|
-
template:
|
|
15345
|
+
template: import_zod8.z.string().min(1).optional(),
|
|
15046
15346
|
direction: CharacterDirectionSchema.optional(),
|
|
15047
|
-
frames:
|
|
15048
|
-
fps:
|
|
15347
|
+
frames: import_zod8.z.number().int().min(4).max(16).optional(),
|
|
15348
|
+
fps: import_zod8.z.number().int().min(1).max(60).optional(),
|
|
15049
15349
|
mode: CharacterAnimationModeSchema.optional(),
|
|
15050
15350
|
/** What is being animated, when the parent's own description would mislead the model (`character` only). */
|
|
15051
|
-
subject:
|
|
15052
|
-
enhancePrompt:
|
|
15351
|
+
subject: import_zod8.z.string().min(1).optional(),
|
|
15352
|
+
enhancePrompt: import_zod8.z.boolean().optional()
|
|
15053
15353
|
}).strict();
|
|
15054
|
-
var NewAssetSchema =
|
|
15055
|
-
prompt:
|
|
15056
|
-
category:
|
|
15057
|
-
width:
|
|
15058
|
-
height:
|
|
15059
|
-
size:
|
|
15060
|
-
tags:
|
|
15354
|
+
var NewAssetSchema = import_zod8.z.object({
|
|
15355
|
+
prompt: import_zod8.z.string(),
|
|
15356
|
+
category: import_zod8.z.string().optional(),
|
|
15357
|
+
width: import_zod8.z.number().int().optional(),
|
|
15358
|
+
height: import_zod8.z.number().int().optional(),
|
|
15359
|
+
size: import_zod8.z.number().int().optional(),
|
|
15360
|
+
tags: import_zod8.z.array(import_zod8.z.string()).optional(),
|
|
15061
15361
|
/** Restrict to these styles; empty or omitted means every style. */
|
|
15062
|
-
styles:
|
|
15362
|
+
styles: import_zod8.z.array(import_zod8.z.string().min(1)).optional(),
|
|
15063
15363
|
/**
|
|
15064
15364
|
* A controlled regeneration of another asset in the same manifest,
|
|
15065
15365
|
* instead of a fresh generation. `inpaint` needs a mask upload the
|
|
15066
15366
|
* gallery does not offer yet, so only `image-to-image` can be created
|
|
15067
15367
|
* here; hand-edit the manifest for the other modes.
|
|
15068
15368
|
*/
|
|
15069
|
-
revision:
|
|
15070
|
-
mode:
|
|
15369
|
+
revision: import_zod8.z.object({
|
|
15370
|
+
mode: import_zod8.z.literal("image-to-image"),
|
|
15071
15371
|
/** Asset id of the parent this revises; must already exist. */
|
|
15072
|
-
from:
|
|
15073
|
-
strength:
|
|
15372
|
+
from: import_zod8.z.string().min(1),
|
|
15373
|
+
strength: import_zod8.z.number().min(0).max(1).optional()
|
|
15074
15374
|
}).strict().optional(),
|
|
15075
15375
|
/** A pose or outfit of an existing `character`/`objectPro` base or state. */
|
|
15076
15376
|
state: NewStateSchema.optional(),
|
|
@@ -15086,58 +15386,58 @@ var CANDIDATE_OPTION = {
|
|
|
15086
15386
|
comfyui: "numImages",
|
|
15087
15387
|
scenario: "numOutputs"
|
|
15088
15388
|
};
|
|
15089
|
-
var ManifestEditSchema =
|
|
15090
|
-
|
|
15091
|
-
action:
|
|
15389
|
+
var ManifestEditSchema = import_zod8.z.discriminatedUnion("action", [
|
|
15390
|
+
import_zod8.z.object({
|
|
15391
|
+
action: import_zod8.z.literal("patch-asset"),
|
|
15092
15392
|
/** Workspace project id; omitted for a single-project gallery. */
|
|
15093
|
-
project:
|
|
15094
|
-
assetId:
|
|
15393
|
+
project: import_zod8.z.string().min(1).optional(),
|
|
15394
|
+
assetId: import_zod8.z.string().min(1),
|
|
15095
15395
|
/** Manifest bytes the page last saw; a mismatch refuses the write. */
|
|
15096
15396
|
expectedSha256: HexSha,
|
|
15097
15397
|
patch: AssetPatchSchema
|
|
15098
15398
|
}).strict(),
|
|
15099
|
-
|
|
15100
|
-
action:
|
|
15101
|
-
project:
|
|
15102
|
-
assetId:
|
|
15399
|
+
import_zod8.z.object({
|
|
15400
|
+
action: import_zod8.z.literal("add-asset"),
|
|
15401
|
+
project: import_zod8.z.string().min(1).optional(),
|
|
15402
|
+
assetId: import_zod8.z.string().min(1).regex(/^[^/\\]+$/, "asset ids cannot contain slashes"),
|
|
15103
15403
|
expectedSha256: HexSha,
|
|
15104
15404
|
asset: NewAssetSchema
|
|
15105
15405
|
}).strict(),
|
|
15106
|
-
|
|
15107
|
-
action:
|
|
15108
|
-
project:
|
|
15109
|
-
assetId:
|
|
15110
|
-
styleId:
|
|
15406
|
+
import_zod8.z.object({
|
|
15407
|
+
action: import_zod8.z.literal("set-source"),
|
|
15408
|
+
project: import_zod8.z.string().min(1).optional(),
|
|
15409
|
+
assetId: import_zod8.z.string().min(1),
|
|
15410
|
+
styleId: import_zod8.z.string().min(1),
|
|
15111
15411
|
/** Manifest-relative path of the art that stands in for this asset in this style. */
|
|
15112
|
-
source:
|
|
15412
|
+
source: import_zod8.z.string().min(1),
|
|
15113
15413
|
expectedSha256: HexSha
|
|
15114
15414
|
}).strict(),
|
|
15115
|
-
|
|
15116
|
-
action:
|
|
15117
|
-
project:
|
|
15118
|
-
assetId:
|
|
15119
|
-
styleId:
|
|
15415
|
+
import_zod8.z.object({
|
|
15416
|
+
action: import_zod8.z.literal("clear-source"),
|
|
15417
|
+
project: import_zod8.z.string().min(1).optional(),
|
|
15418
|
+
assetId: import_zod8.z.string().min(1),
|
|
15419
|
+
styleId: import_zod8.z.string().min(1),
|
|
15120
15420
|
expectedSha256: HexSha
|
|
15121
15421
|
}).strict(),
|
|
15122
|
-
|
|
15123
|
-
action:
|
|
15124
|
-
project:
|
|
15125
|
-
styleId:
|
|
15422
|
+
import_zod8.z.object({
|
|
15423
|
+
action: import_zod8.z.literal("patch-style"),
|
|
15424
|
+
project: import_zod8.z.string().min(1).optional(),
|
|
15425
|
+
styleId: import_zod8.z.string().min(1),
|
|
15126
15426
|
expectedSha256: HexSha,
|
|
15127
|
-
patch:
|
|
15427
|
+
patch: import_zod8.z.object({
|
|
15128
15428
|
/** Candidates per generation, written to the provider's own option. */
|
|
15129
|
-
candidates:
|
|
15429
|
+
candidates: import_zod8.z.number().int().min(1).max(64).optional(),
|
|
15130
15430
|
/** Empty clears the style's own value (inherit, or the default). */
|
|
15131
|
-
promptPrefix:
|
|
15132
|
-
promptSuffix:
|
|
15431
|
+
promptPrefix: import_zod8.z.string().optional(),
|
|
15432
|
+
promptSuffix: import_zod8.z.string().optional(),
|
|
15133
15433
|
/** `#rrggbb` values; null or empty clears the style's own palette. */
|
|
15134
|
-
palette:
|
|
15434
|
+
palette: import_zod8.z.array(import_zod8.z.string().regex(/^#?[0-9a-f]{6}$/i, "expected a six-digit hex colour")).max(256).nullable().optional(),
|
|
15135
15435
|
/** Snap downloaded art to the palette; false clears the style's own value. */
|
|
15136
|
-
enforcePalette:
|
|
15436
|
+
enforcePalette: import_zod8.z.boolean().optional(),
|
|
15137
15437
|
/** Provider view name (PixelLab: low top-down, high top-down, side); empty clears. */
|
|
15138
|
-
view:
|
|
15438
|
+
view: import_zod8.z.string().max(64).nullable().optional(),
|
|
15139
15439
|
/** pixflux only; null clears the style's own value. */
|
|
15140
|
-
noBackground:
|
|
15440
|
+
noBackground: import_zod8.z.boolean().nullable().optional()
|
|
15141
15441
|
}).strict().refine((patch) => Object.keys(patch).length > 0, { message: "nothing to change" })
|
|
15142
15442
|
}).strict()
|
|
15143
15443
|
]);
|
|
@@ -15331,7 +15631,7 @@ async function applyManifestEdit(manifestPath, edit) {
|
|
|
15331
15631
|
var import_node_fs24 = require("fs");
|
|
15332
15632
|
var import_promises21 = require("fs/promises");
|
|
15333
15633
|
var import_node_path28 = __toESM(require("path"), 1);
|
|
15334
|
-
var
|
|
15634
|
+
var import_zod9 = require("zod");
|
|
15335
15635
|
var HAND_EDIT_DIR = "edits";
|
|
15336
15636
|
function handEditPath(loaded, spec) {
|
|
15337
15637
|
const style = loaded.manifest.styles[spec.styleId];
|
|
@@ -15428,35 +15728,35 @@ async function detachHandEdit(loaded, spec, opts = {}) {
|
|
|
15428
15728
|
});
|
|
15429
15729
|
return { manifestSha256: result.sha256, changed: result.changed };
|
|
15430
15730
|
}
|
|
15431
|
-
var CompanionOutputSchema =
|
|
15731
|
+
var CompanionOutputSchema = import_zod9.z.object({
|
|
15432
15732
|
/** Output role for a set member; null for a single image. */
|
|
15433
|
-
role:
|
|
15733
|
+
role: import_zod9.z.string().nullable(),
|
|
15434
15734
|
/** sha256 of the generated file this member started from; null when it started from untracked art. */
|
|
15435
|
-
basedOn:
|
|
15735
|
+
basedOn: import_zod9.z.string().regex(/^[0-9a-f]{64}$/).nullable(),
|
|
15436
15736
|
/** sha256 of the member as saved, so a later change by another tool is visible. */
|
|
15437
|
-
sha256:
|
|
15737
|
+
sha256: import_zod9.z.string().regex(/^[0-9a-f]{64}$/)
|
|
15438
15738
|
}).strict();
|
|
15439
|
-
var CompanionV2Schema =
|
|
15440
|
-
version:
|
|
15739
|
+
var CompanionV2Schema = import_zod9.z.object({
|
|
15740
|
+
version: import_zod9.z.literal(2),
|
|
15441
15741
|
/** Editor identity the bridge reported, e.g. `pixelorama@v1.2.2-stable`. */
|
|
15442
|
-
editor:
|
|
15443
|
-
protocol:
|
|
15444
|
-
savedAt:
|
|
15742
|
+
editor: import_zod9.z.string().min(1),
|
|
15743
|
+
protocol: import_zod9.z.number().int().positive(),
|
|
15744
|
+
savedAt: import_zod9.z.string().datetime(),
|
|
15445
15745
|
/** Basename of the layered project file beside the edit, when one was kept. */
|
|
15446
|
-
project:
|
|
15746
|
+
project: import_zod9.z.string().min(1).nullable(),
|
|
15447
15747
|
/** One entry per file, in output order. */
|
|
15448
|
-
outputs:
|
|
15748
|
+
outputs: import_zod9.z.array(CompanionOutputSchema).min(1)
|
|
15449
15749
|
}).strict();
|
|
15450
|
-
var CompanionV1Schema =
|
|
15451
|
-
version:
|
|
15452
|
-
basedOn:
|
|
15453
|
-
sha256:
|
|
15454
|
-
editor:
|
|
15455
|
-
protocol:
|
|
15456
|
-
savedAt:
|
|
15457
|
-
project:
|
|
15750
|
+
var CompanionV1Schema = import_zod9.z.object({
|
|
15751
|
+
version: import_zod9.z.literal(1),
|
|
15752
|
+
basedOn: import_zod9.z.string().regex(/^[0-9a-f]{64}$/).nullable(),
|
|
15753
|
+
sha256: import_zod9.z.string().regex(/^[0-9a-f]{64}$/),
|
|
15754
|
+
editor: import_zod9.z.string().min(1),
|
|
15755
|
+
protocol: import_zod9.z.number().int().positive(),
|
|
15756
|
+
savedAt: import_zod9.z.string().datetime(),
|
|
15757
|
+
project: import_zod9.z.string().min(1).nullable()
|
|
15458
15758
|
}).strict();
|
|
15459
|
-
var HandEditCompanionSchema =
|
|
15759
|
+
var HandEditCompanionSchema = import_zod9.z.union([CompanionV2Schema, CompanionV1Schema]).transform(
|
|
15460
15760
|
(value) => value.version === 2 ? value : {
|
|
15461
15761
|
version: 2,
|
|
15462
15762
|
editor: value.editor,
|
|
@@ -15576,40 +15876,40 @@ function openInEditor(file, editor = process.env.PIXELKILN_EDITOR) {
|
|
|
15576
15876
|
}
|
|
15577
15877
|
|
|
15578
15878
|
// src/gallery/edit.ts
|
|
15579
|
-
var Base64 =
|
|
15580
|
-
var HandEditRequestSchema =
|
|
15581
|
-
|
|
15582
|
-
action:
|
|
15583
|
-
project:
|
|
15584
|
-
assetId:
|
|
15585
|
-
styleId:
|
|
15586
|
-
expectedSha256:
|
|
15879
|
+
var Base64 = import_zod10.z.string().regex(/^[A-Za-z0-9+/]*={0,2}$/).max(Math.ceil(MAX_HAND_EDIT_BYTES / 3) * 4);
|
|
15880
|
+
var HandEditRequestSchema = import_zod10.z.discriminatedUnion("action", [
|
|
15881
|
+
import_zod10.z.object({
|
|
15882
|
+
action: import_zod10.z.literal("start-edit"),
|
|
15883
|
+
project: import_zod10.z.string().min(1).optional(),
|
|
15884
|
+
assetId: import_zod10.z.string().min(1),
|
|
15885
|
+
styleId: import_zod10.z.string().min(1),
|
|
15886
|
+
expectedSha256: import_zod10.z.string().regex(/^[0-9a-f]{64}$/),
|
|
15587
15887
|
/** Also launch the author's editor on the file. */
|
|
15588
|
-
open:
|
|
15888
|
+
open: import_zod10.z.boolean().optional()
|
|
15589
15889
|
}).strict(),
|
|
15590
|
-
|
|
15591
|
-
action:
|
|
15592
|
-
project:
|
|
15593
|
-
assetId:
|
|
15594
|
-
styleId:
|
|
15595
|
-
expectedSha256:
|
|
15890
|
+
import_zod10.z.object({
|
|
15891
|
+
action: import_zod10.z.literal("detach-edit"),
|
|
15892
|
+
project: import_zod10.z.string().min(1).optional(),
|
|
15893
|
+
assetId: import_zod10.z.string().min(1),
|
|
15894
|
+
styleId: import_zod10.z.string().min(1),
|
|
15895
|
+
expectedSha256: import_zod10.z.string().regex(/^[0-9a-f]{64}$/)
|
|
15596
15896
|
}).strict(),
|
|
15597
15897
|
/** From the in-browser editor: the page holds the bytes, the server validates and writes. */
|
|
15598
|
-
|
|
15599
|
-
action:
|
|
15600
|
-
project:
|
|
15601
|
-
assetId:
|
|
15602
|
-
styleId:
|
|
15603
|
-
expectedSha256:
|
|
15898
|
+
import_zod10.z.object({
|
|
15899
|
+
action: import_zod10.z.literal("save-edit"),
|
|
15900
|
+
project: import_zod10.z.string().min(1).optional(),
|
|
15901
|
+
assetId: import_zod10.z.string().min(1),
|
|
15902
|
+
styleId: import_zod10.z.string().min(1),
|
|
15903
|
+
expectedSha256: import_zod10.z.string().regex(/^[0-9a-f]{64}$/),
|
|
15604
15904
|
/** The flattened image; for a frame set, `frames` instead. */
|
|
15605
15905
|
png: Base64.min(1).optional(),
|
|
15606
15906
|
/** Every frame of a set, tagged with the role it was opened under (null for one added in the editor). */
|
|
15607
|
-
frames:
|
|
15907
|
+
frames: import_zod10.z.array(import_zod10.z.object({ role: import_zod10.z.string().min(1).nullable(), png: Base64.min(1) }).strict()).min(1).max(256).optional(),
|
|
15608
15908
|
/** The editor's layered project file, kept beside the edit. */
|
|
15609
15909
|
pxo: Base64.optional(),
|
|
15610
15910
|
/** Editor identity from the bridge's ready message. */
|
|
15611
|
-
editor:
|
|
15612
|
-
protocol:
|
|
15911
|
+
editor: import_zod10.z.string().min(1).max(200),
|
|
15912
|
+
protocol: import_zod10.z.number().int().positive()
|
|
15613
15913
|
}).strict()
|
|
15614
15914
|
]);
|
|
15615
15915
|
function createGalleryEditHandler(opts) {
|
|
@@ -16943,27 +17243,27 @@ async function serveGallery(opts) {
|
|
|
16943
17243
|
|
|
16944
17244
|
// src/gallery/generate.ts
|
|
16945
17245
|
var import_node_crypto9 = require("crypto");
|
|
16946
|
-
var
|
|
16947
|
-
var GenerateRequestSchema =
|
|
16948
|
-
project:
|
|
16949
|
-
keys:
|
|
17246
|
+
var import_zod11 = require("zod");
|
|
17247
|
+
var GenerateRequestSchema = import_zod11.z.object({
|
|
17248
|
+
project: import_zod11.z.string().min(1).optional(),
|
|
17249
|
+
keys: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).max(500),
|
|
16950
17250
|
/**
|
|
16951
17251
|
* Regenerate work that is up to date, as `gen --force` does, and let the
|
|
16952
17252
|
* fetch replace a locally modified or untracked file. With `restore`, put
|
|
16953
17253
|
* the recorded bytes back over a modified file.
|
|
16954
17254
|
*/
|
|
16955
|
-
force:
|
|
17255
|
+
force: import_zod11.z.boolean().optional(),
|
|
16956
17256
|
/** Advance in-flight, review, or selected work without submitting anything. */
|
|
16957
|
-
resume:
|
|
17257
|
+
resume: import_zod11.z.boolean().optional(),
|
|
16958
17258
|
/** Re-download downloaded outputs and replace files whose object changed upstream. */
|
|
16959
|
-
refresh:
|
|
17259
|
+
refresh: import_zod11.z.boolean().optional(),
|
|
16960
17260
|
/** Put recorded outputs back on disk from the cache or the provider, without generating. */
|
|
16961
|
-
restore:
|
|
17261
|
+
restore: import_zod11.z.boolean().optional(),
|
|
16962
17262
|
/**
|
|
16963
17263
|
* Bring a replaced generation back: 1-based position in the record's
|
|
16964
17264
|
* history (newest first) or an output hash prefix. One key at a time.
|
|
16965
17265
|
*/
|
|
16966
|
-
revert:
|
|
17266
|
+
revert: import_zod11.z.string().min(1).max(64).optional()
|
|
16967
17267
|
}).strict().refine((request) => [request.resume, request.refresh, request.restore, request.revert !== void 0].filter(Boolean).length <= 1, {
|
|
16968
17268
|
message: "resume, refresh, restore, and revert are exclusive"
|
|
16969
17269
|
}).refine((request) => request.revert === void 0 || request.keys.length === 1, { message: "revert takes one key" });
|
|
@@ -17967,6 +18267,8 @@ async function workspaceStatus(ws, dir) {
|
|
|
17967
18267
|
ManifestEditSchema,
|
|
17968
18268
|
ManifestInputSchema,
|
|
17969
18269
|
ManifestSchema,
|
|
18270
|
+
MapScenePlacementSchema,
|
|
18271
|
+
MapSceneSchema,
|
|
17970
18272
|
MediaType,
|
|
17971
18273
|
OverwriteRefusedError,
|
|
17972
18274
|
PIXEL_ART_FIXER_REVISION,
|