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/cli.js
CHANGED
|
@@ -68,7 +68,7 @@ function exitCodeFor(err) {
|
|
|
68
68
|
|
|
69
69
|
// src/cli/main.ts
|
|
70
70
|
import { existsSync as existsSync33 } from "fs";
|
|
71
|
-
import { readFile as
|
|
71
|
+
import { readFile as readFile31 } from "fs/promises";
|
|
72
72
|
|
|
73
73
|
// src/cli/args.ts
|
|
74
74
|
import path from "path";
|
|
@@ -157,6 +157,7 @@ var COMMANDS = [
|
|
|
157
157
|
"refine",
|
|
158
158
|
"recipe",
|
|
159
159
|
"workspace",
|
|
160
|
+
"estimate-skeleton",
|
|
160
161
|
"unzoom",
|
|
161
162
|
"font",
|
|
162
163
|
"help",
|
|
@@ -251,6 +252,10 @@ function parseArgs(argv) {
|
|
|
251
252
|
}
|
|
252
253
|
rest = rest.slice(1);
|
|
253
254
|
}
|
|
255
|
+
} else if (command === "estimate-skeleton") {
|
|
256
|
+
target = rest[0]?.startsWith("-") ? void 0 : rest[0];
|
|
257
|
+
if (target === void 0) throw new UsageError("estimate-skeleton needs an image path");
|
|
258
|
+
rest = rest.slice(1);
|
|
254
259
|
} else if (command === "refine") {
|
|
255
260
|
subcommand = rest[0]?.startsWith("-") || rest[0] === void 0 ? "run" : rest[0];
|
|
256
261
|
if (!REFINE_SUBCOMMANDS.includes(subcommand)) {
|
|
@@ -456,6 +461,11 @@ Commands
|
|
|
456
461
|
first. Local art is untouched.
|
|
457
462
|
tag Push manifest tags to the objects upstream (free).
|
|
458
463
|
balance Show the provider's remaining balance.
|
|
464
|
+
estimate-skeleton <image> [--out <file>]
|
|
465
|
+
PixelLab only: derive an 18-joint skeleton from an image, direct
|
|
466
|
+
and un-budgeted (like balance, not a generation). Prints the
|
|
467
|
+
keypoints JSON, or writes it with --out \u2014 the way to bootstrap
|
|
468
|
+
an animate-skeleton revision's keypointsFile.
|
|
459
469
|
status Summarise the lockfile.
|
|
460
470
|
edit Hand-edit an asset in your own editor: copies the generated PNG to
|
|
461
471
|
<outDir>/edits/, declares it as the asset's source, and opens it.
|
|
@@ -638,10 +648,10 @@ import { createReadStream } from "fs";
|
|
|
638
648
|
function sha256(data) {
|
|
639
649
|
return createHash("sha256").update(data).digest("hex");
|
|
640
650
|
}
|
|
641
|
-
async function sha256File(
|
|
651
|
+
async function sha256File(path48) {
|
|
642
652
|
return new Promise((resolve, reject) => {
|
|
643
653
|
const hash = createHash("sha256");
|
|
644
|
-
const stream = createReadStream(
|
|
654
|
+
const stream = createReadStream(path48);
|
|
645
655
|
stream.on("data", (chunk2) => hash.update(chunk2));
|
|
646
656
|
stream.on("error", reject);
|
|
647
657
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -679,6 +689,11 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
679
689
|
uiPieces: spec.uiPieces,
|
|
680
690
|
uiElements: spec.uiElements,
|
|
681
691
|
uiColorPalette: spec.uiColorPalette,
|
|
692
|
+
// Scene and mask enter as their bytes' hashes, never their paths.
|
|
693
|
+
scene: spec.scene ? {
|
|
694
|
+
image: spec.scene.sha256,
|
|
695
|
+
placement: spec.scene.placement.type === "mask" ? { type: "mask", mask: spec.scene.placement.sha256 } : spec.scene.placement
|
|
696
|
+
} : void 0,
|
|
682
697
|
styleTraits: spec.styleTraits,
|
|
683
698
|
styleImages: styleImageHashes,
|
|
684
699
|
// A character family: the engine and rotations of a base, the parent's
|
|
@@ -757,6 +772,9 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
757
772
|
lastFrameSha256: spec.revision.lastFrameSha256,
|
|
758
773
|
direction: spec.revision.direction,
|
|
759
774
|
enhancePrompt: spec.revision.enhancePrompt,
|
|
775
|
+
keypointsSha256: spec.revision.keypointsSha256,
|
|
776
|
+
skeletonTemplate: spec.revision.skeletonTemplate,
|
|
777
|
+
description: spec.revision.description,
|
|
760
778
|
engine: spec.revision.engine
|
|
761
779
|
} : void 0
|
|
762
780
|
})
|
|
@@ -785,6 +803,7 @@ var RevisionModeSchema = z.enum([
|
|
|
785
803
|
"correct-pixelart",
|
|
786
804
|
"animate",
|
|
787
805
|
"animate-pixminimax",
|
|
806
|
+
"animate-skeleton",
|
|
788
807
|
"interpolate",
|
|
789
808
|
"edit-animation"
|
|
790
809
|
]);
|
|
@@ -973,6 +992,16 @@ var CharacterPortraitSchema = z.object({
|
|
|
973
992
|
of: z.string().min(1),
|
|
974
993
|
size: CharacterPortraitSizeSchema.default(64)
|
|
975
994
|
}).strict();
|
|
995
|
+
var MapScenePlacementSchema = z.union([
|
|
996
|
+
z.object({ oval: z.number().min(0.05).max(0.95) }).strict(),
|
|
997
|
+
z.object({ rectangle: z.number().min(0.05).max(0.95) }).strict(),
|
|
998
|
+
z.object({ mask: z.string().min(1) }).strict()
|
|
999
|
+
]);
|
|
1000
|
+
var MapSceneSchema = z.object({
|
|
1001
|
+
/** Manifest-relative PNG of the scene. Any earlier asset's output file works. */
|
|
1002
|
+
image: z.string().min(1),
|
|
1003
|
+
placement: MapScenePlacementSchema.default({ oval: 0.3 })
|
|
1004
|
+
}).strict();
|
|
976
1005
|
var CharacterOutfitSchema = z.object({
|
|
977
1006
|
/** The loop (a character animation asset) to re-clothe, in the same style. */
|
|
978
1007
|
of: z.string().min(1),
|
|
@@ -1103,6 +1132,30 @@ var RevisionSchema = z.object({
|
|
|
1103
1132
|
direction: CharacterDirectionSchema.optional(),
|
|
1104
1133
|
/** `animate`/`animate-pixminimax` only: let PixelLab expand the action into a fuller motion description first. */
|
|
1105
1134
|
enhancePrompt: z.boolean().optional(),
|
|
1135
|
+
/**
|
|
1136
|
+
* `animate-skeleton` only: manifest-relative path to a committed
|
|
1137
|
+
* `SkeletonSet` JSON file (see `src/skeleton.ts`) — the pose the parent
|
|
1138
|
+
* image is already in, plus 3-15 per-frame poses for the motion.
|
|
1139
|
+
* Authored via `pixelkiln estimate-skeleton`, then hand-tweaked; never
|
|
1140
|
+
* inline in the manifest, the same reasoning `mask`/`lastFrame` are
|
|
1141
|
+
* committed files rather than inline pixel data.
|
|
1142
|
+
*/
|
|
1143
|
+
keypointsFile: z.string().min(1).optional(),
|
|
1144
|
+
/**
|
|
1145
|
+
* `animate-skeleton` only: the body a joint's missing `depth` is taken
|
|
1146
|
+
* from. PixelLab's default is `mannequin`; free string like `character`'s
|
|
1147
|
+
* own `template` field, validated at the provider layer against the
|
|
1148
|
+
* same `mannequin`/`bear`/`cat`/`dog`/`horse`/`lion` vocabulary.
|
|
1149
|
+
*/
|
|
1150
|
+
skeletonTemplate: z.string().min(1).optional(),
|
|
1151
|
+
/**
|
|
1152
|
+
* `animate-skeleton` only: what the character *looks like*, a noun
|
|
1153
|
+
* phrase (colours, clothing, held items) — distinct from the asset's
|
|
1154
|
+
* own `prompt`, which this mode sends as the motion's short label
|
|
1155
|
+
* (PixelLab's `action`), the same `prompt`-as-motion convention
|
|
1156
|
+
* `animate`/`animate-pixminimax` already use.
|
|
1157
|
+
*/
|
|
1158
|
+
description: z.string().min(1).optional(),
|
|
1106
1159
|
/**
|
|
1107
1160
|
* `image-to-image`/`inpaint` only: which provider engine draws the
|
|
1108
1161
|
* edit. `pro-flash` selects PixelLab's Pro Flash edit and inpaint tier
|
|
@@ -1193,18 +1246,41 @@ var RevisionSchema = z.object({
|
|
|
1193
1246
|
path: ["fps"]
|
|
1194
1247
|
});
|
|
1195
1248
|
}
|
|
1196
|
-
if (revision.direction !== void 0 && revision.mode !== "animate-pixminimax") {
|
|
1249
|
+
if (revision.direction !== void 0 && revision.mode !== "animate-pixminimax" && revision.mode !== "animate-skeleton") {
|
|
1250
|
+
context.addIssue({
|
|
1251
|
+
code: z.ZodIssueCode.custom,
|
|
1252
|
+
message: "direction applies to animate-pixminimax/animate-skeleton revisions only",
|
|
1253
|
+
path: ["direction"]
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
if (revision.mode === "animate-skeleton" && revision.direction === void 0) {
|
|
1197
1257
|
context.addIssue({
|
|
1198
1258
|
code: z.ZodIssueCode.custom,
|
|
1199
|
-
message: "
|
|
1259
|
+
message: "animate-skeleton revisions require a direction",
|
|
1200
1260
|
path: ["direction"]
|
|
1201
1261
|
});
|
|
1202
1262
|
}
|
|
1203
1263
|
if (revision.frames !== void 0 && revision.frames % 2 !== 0) {
|
|
1204
1264
|
context.addIssue({ code: z.ZodIssueCode.custom, message: "frames must be even", path: ["frames"] });
|
|
1205
1265
|
}
|
|
1266
|
+
if (revision.mode === "animate-skeleton" && !revision.keypointsFile) {
|
|
1267
|
+
context.addIssue({
|
|
1268
|
+
code: z.ZodIssueCode.custom,
|
|
1269
|
+
message: "animate-skeleton revisions require keypointsFile",
|
|
1270
|
+
path: ["keypointsFile"]
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
for (const field of ["keypointsFile", "skeletonTemplate", "description"]) {
|
|
1274
|
+
if (revision[field] !== void 0 && revision.mode !== "animate-skeleton") {
|
|
1275
|
+
context.addIssue({
|
|
1276
|
+
code: z.ZodIssueCode.custom,
|
|
1277
|
+
message: `${field} applies to animate-skeleton revisions only`,
|
|
1278
|
+
path: [field]
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1206
1282
|
});
|
|
1207
|
-
var FRAME_SET_REVISION_MODES = ["animate", "animate-pixminimax", "interpolate", "edit-animation"];
|
|
1283
|
+
var FRAME_SET_REVISION_MODES = ["animate", "animate-pixminimax", "animate-skeleton", "interpolate", "edit-animation"];
|
|
1208
1284
|
var MEMBER_SET_REVISION_MODES = ["reduce-colors", "correct-pixelart", "edit-animation"];
|
|
1209
1285
|
var StyleObjectSchema = z.object({
|
|
1210
1286
|
/** Generation backend for this style. Omit to inherit the manifest default. */
|
|
@@ -1620,6 +1696,8 @@ var AssetSchema = z.object({
|
|
|
1620
1696
|
portrait: CharacterPortraitSchema.optional(),
|
|
1621
1697
|
/** `character` styles: this asset re-clothes an existing loop's frames with a reference outfit. */
|
|
1622
1698
|
outfit: CharacterOutfitSchema.optional(),
|
|
1699
|
+
/** `map` styles only: draw this object in the style of a scene image. See `MapSceneSchema`. */
|
|
1700
|
+
scene: MapSceneSchema.optional(),
|
|
1623
1701
|
/** `character` styles, `standard` humanoid bases: this character's proportions, over the style's. */
|
|
1624
1702
|
proportions: CharacterProportionsSchema.optional(),
|
|
1625
1703
|
/**
|
|
@@ -1696,7 +1774,7 @@ var AssetSchema = z.object({
|
|
|
1696
1774
|
path: ["revision"]
|
|
1697
1775
|
});
|
|
1698
1776
|
}
|
|
1699
|
-
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);
|
|
1777
|
+
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);
|
|
1700
1778
|
if (shapes.length > 1) {
|
|
1701
1779
|
context.addIssue({
|
|
1702
1780
|
code: z.ZodIssueCode.custom,
|
|
@@ -1836,11 +1914,16 @@ var LockEntrySchema = z.object({
|
|
|
1836
1914
|
paletteImageSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1837
1915
|
dithering: RevisionDitheringSchema.optional(),
|
|
1838
1916
|
ditheringStrength: z.number().min(0).max(10).optional(),
|
|
1839
|
-
|
|
1917
|
+
// 4-40 for animate/animate-pixminimax; animate-skeleton's own 3-15
|
|
1918
|
+
// range extends the floor down to 3, hence min(3) here rather than 4.
|
|
1919
|
+
frames: z.number().int().min(3).max(40).optional(),
|
|
1840
1920
|
fps: z.number().int().min(1).max(60).optional(),
|
|
1841
1921
|
lastFrameSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1842
1922
|
direction: CharacterDirectionSchema.optional(),
|
|
1843
1923
|
enhancePrompt: z.boolean().optional(),
|
|
1924
|
+
keypointsSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
1925
|
+
skeletonTemplate: z.string().min(1).optional(),
|
|
1926
|
+
description: z.string().min(1).optional(),
|
|
1844
1927
|
engine: z.enum(["pro-flash"]).optional()
|
|
1845
1928
|
}).strict().nullable().default(null),
|
|
1846
1929
|
/** For a mirror: the asset it flips and a hash over that asset's output hashes when this was made. */
|
|
@@ -4146,6 +4229,7 @@ async function inspectRevisionReadiness(spec, lock) {
|
|
|
4146
4229
|
if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
|
|
4147
4230
|
if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
|
|
4148
4231
|
if (spec.objectPro?.parentSpec) return inspectObjectProParent(spec, lock, /* @__PURE__ */ new Set());
|
|
4232
|
+
if (spec.scene) return inspectScene(spec);
|
|
4149
4233
|
if (!spec.revision) return null;
|
|
4150
4234
|
return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
|
|
4151
4235
|
}
|
|
@@ -4163,6 +4247,16 @@ async function inspectStyleAnchor(spec, lock, seen) {
|
|
|
4163
4247
|
}
|
|
4164
4248
|
return { ready: true, reason: `${label} is current` };
|
|
4165
4249
|
}
|
|
4250
|
+
async function inspectScene(spec) {
|
|
4251
|
+
const scene = spec.scene;
|
|
4252
|
+
const files = [{ label: "scene image", file: scene.file, sha256: scene.sha256 }];
|
|
4253
|
+
if (scene.placement.type === "mask") files.push({ label: "scene mask", file: scene.placement.file, sha256: scene.placement.sha256 });
|
|
4254
|
+
for (const { label, file, sha256: sha2562 } of files) {
|
|
4255
|
+
if (!sha2562 || !existsSync4(file)) return { ready: false, reason: `${label} does not exist yet: ${file}` };
|
|
4256
|
+
if (await sha256File(file) !== sha2562) return { ready: false, reason: `${label} changed after the manifest was resolved` };
|
|
4257
|
+
}
|
|
4258
|
+
return { ready: true, reason: "scene is current" };
|
|
4259
|
+
}
|
|
4166
4260
|
async function inspectMirror(spec, lock, seen) {
|
|
4167
4261
|
const source = spec.mirror.sourceSpec;
|
|
4168
4262
|
const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
|
|
@@ -4993,11 +5087,12 @@ var ComfyUIProvider = class _ComfyUIProvider {
|
|
|
4993
5087
|
/**
|
|
4994
5088
|
* Everything else resolves generically to whatever the user's own
|
|
4995
5089
|
* workflow does with `bindings.sourceImage`. The frame-set modes
|
|
4996
|
-
* (`animate`, `animate-pixminimax`, `
|
|
4997
|
-
* the exception: they produce an ordered frame set,
|
|
4998
|
-
* revision path always writes a single output image
|
|
4999
|
-
* below) — a real structural gap, not a missing
|
|
5000
|
-
* rejected here rather than only failing once
|
|
5090
|
+
* (`animate`, `animate-pixminimax`, `animate-skeleton`, `interpolate`,
|
|
5091
|
+
* `edit-animation`) are the exception: they produce an ordered frame set,
|
|
5092
|
+
* and this adapter's revision path always writes a single output image
|
|
5093
|
+
* (see `submit`/`fetch` below) — a real structural gap, not a missing
|
|
5094
|
+
* binding, so they are rejected here rather than only failing once
|
|
5095
|
+
* `validate` runs.
|
|
5001
5096
|
*/
|
|
5002
5097
|
supportsRevision(mode2) {
|
|
5003
5098
|
return !FRAME_SET_REVISION_MODES.includes(mode2);
|
|
@@ -5657,262 +5752,291 @@ import os from "os";
|
|
|
5657
5752
|
import path12 from "path";
|
|
5658
5753
|
|
|
5659
5754
|
// src/client.ts
|
|
5755
|
+
import { z as z3 } from "zod";
|
|
5756
|
+
|
|
5757
|
+
// src/skeleton.ts
|
|
5660
5758
|
import { z as z2 } from "zod";
|
|
5759
|
+
var SkeletonKeypointSchema = z2.object({
|
|
5760
|
+
label: z2.string().min(1),
|
|
5761
|
+
x: z2.number().min(0).max(1),
|
|
5762
|
+
y: z2.number().min(0).max(1),
|
|
5763
|
+
z_index: z2.number(),
|
|
5764
|
+
depth: z2.number().optional()
|
|
5765
|
+
}).strict();
|
|
5766
|
+
var SkeletonFrameSchema = z2.array(SkeletonKeypointSchema).length(18);
|
|
5767
|
+
var SkeletonSetSchema = z2.object({
|
|
5768
|
+
firstFrameKeypoints: SkeletonFrameSchema,
|
|
5769
|
+
frames: z2.array(SkeletonFrameSchema).min(3).max(15)
|
|
5770
|
+
}).strict();
|
|
5771
|
+
function parseSkeletonSet(json, file) {
|
|
5772
|
+
const result = SkeletonSetSchema.safeParse(json);
|
|
5773
|
+
if (!result.success) {
|
|
5774
|
+
const issues = result.error.issues.slice(0, 4).map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join("; ");
|
|
5775
|
+
throw new Error(`revision keypoints file ${file} does not match the expected shape: ${issues}`);
|
|
5776
|
+
}
|
|
5777
|
+
return result.data;
|
|
5778
|
+
}
|
|
5779
|
+
|
|
5780
|
+
// src/client.ts
|
|
5661
5781
|
var BASE = process.env.PIXELLAB_API_BASE ?? "https://api.pixellab.ai/v2";
|
|
5662
5782
|
var MAX_DOWNLOAD_BYTES = 64 * 1024 * 1024;
|
|
5663
|
-
var BalanceResponseSchema =
|
|
5664
|
-
credits:
|
|
5665
|
-
subscription:
|
|
5666
|
-
generations:
|
|
5667
|
-
total:
|
|
5668
|
-
plan:
|
|
5783
|
+
var BalanceResponseSchema = z3.object({
|
|
5784
|
+
credits: z3.object({ usd: z3.number() }).passthrough(),
|
|
5785
|
+
subscription: z3.object({
|
|
5786
|
+
generations: z3.number(),
|
|
5787
|
+
total: z3.number(),
|
|
5788
|
+
plan: z3.string().nullable().optional()
|
|
5669
5789
|
}).passthrough()
|
|
5670
5790
|
}).passthrough();
|
|
5671
|
-
var ObjectSubmitSchema =
|
|
5672
|
-
background_job_id:
|
|
5673
|
-
object_id:
|
|
5674
|
-
status:
|
|
5675
|
-
n_frames:
|
|
5791
|
+
var ObjectSubmitSchema = z3.object({
|
|
5792
|
+
background_job_id: z3.string().min(1),
|
|
5793
|
+
object_id: z3.string().min(1),
|
|
5794
|
+
status: z3.string().default("queued"),
|
|
5795
|
+
n_frames: z3.number().int().min(0)
|
|
5676
5796
|
}).passthrough();
|
|
5677
|
-
var MapSubmitSchema =
|
|
5678
|
-
background_job_id:
|
|
5679
|
-
object_id:
|
|
5680
|
-
status:
|
|
5797
|
+
var MapSubmitSchema = z3.object({
|
|
5798
|
+
background_job_id: z3.string().min(1),
|
|
5799
|
+
object_id: z3.string().min(1),
|
|
5800
|
+
status: z3.string().default("processing")
|
|
5681
5801
|
}).passthrough();
|
|
5682
|
-
var UsageSchema =
|
|
5683
|
-
type:
|
|
5684
|
-
usd:
|
|
5685
|
-
generations:
|
|
5802
|
+
var UsageSchema = z3.object({
|
|
5803
|
+
type: z3.string().optional(),
|
|
5804
|
+
usd: z3.number().nullable().optional(),
|
|
5805
|
+
generations: z3.number().nullable().optional()
|
|
5686
5806
|
}).passthrough().nullable().optional();
|
|
5687
|
-
var TilesSubmitSchema =
|
|
5688
|
-
tile_id:
|
|
5689
|
-
background_job_id:
|
|
5690
|
-
status:
|
|
5807
|
+
var TilesSubmitSchema = z3.object({
|
|
5808
|
+
tile_id: z3.string().min(1),
|
|
5809
|
+
background_job_id: z3.string().min(1),
|
|
5810
|
+
status: z3.literal("processing").default("processing")
|
|
5691
5811
|
}).passthrough();
|
|
5692
|
-
var TilesProSchema =
|
|
5693
|
-
storage_urls:
|
|
5694
|
-
kind:
|
|
5695
|
-
tile_rules:
|
|
5812
|
+
var TilesProSchema = z3.object({
|
|
5813
|
+
storage_urls: z3.record(z3.string()),
|
|
5814
|
+
kind: z3.string().nullable().default(null),
|
|
5815
|
+
tile_rules: z3.record(z3.unknown()).nullable().optional()
|
|
5696
5816
|
}).passthrough();
|
|
5697
|
-
var TilesetSubmitSchema =
|
|
5698
|
-
tileset_id:
|
|
5699
|
-
background_job_id:
|
|
5700
|
-
status:
|
|
5817
|
+
var TilesetSubmitSchema = z3.object({
|
|
5818
|
+
tileset_id: z3.string().min(1),
|
|
5819
|
+
background_job_id: z3.string().min(1),
|
|
5820
|
+
status: z3.literal("processing").default("processing")
|
|
5701
5821
|
}).passthrough();
|
|
5702
|
-
var TilesetTileSchema =
|
|
5703
|
-
id:
|
|
5704
|
-
name:
|
|
5705
|
-
image:
|
|
5706
|
-
corners:
|
|
5707
|
-
pattern_4x4:
|
|
5708
|
-
row_0:
|
|
5709
|
-
row_1:
|
|
5710
|
-
row_2:
|
|
5711
|
-
row_3:
|
|
5822
|
+
var TilesetTileSchema = z3.object({
|
|
5823
|
+
id: z3.string().min(1),
|
|
5824
|
+
name: z3.string(),
|
|
5825
|
+
image: z3.object({ base64: z3.string().min(1), format: z3.string().default("png") }).passthrough(),
|
|
5826
|
+
corners: z3.object({ NW: z3.string(), NE: z3.string(), SW: z3.string(), SE: z3.string() }).passthrough(),
|
|
5827
|
+
pattern_4x4: z3.object({
|
|
5828
|
+
row_0: z3.array(z3.number()),
|
|
5829
|
+
row_1: z3.array(z3.number()),
|
|
5830
|
+
row_2: z3.array(z3.number()),
|
|
5831
|
+
row_3: z3.array(z3.number())
|
|
5712
5832
|
}).passthrough()
|
|
5713
5833
|
}).passthrough();
|
|
5714
|
-
var TilesetGetSchema =
|
|
5715
|
-
tileset:
|
|
5716
|
-
total_tiles:
|
|
5717
|
-
tile_size:
|
|
5718
|
-
terrain_types:
|
|
5719
|
-
tiles:
|
|
5834
|
+
var TilesetGetSchema = z3.object({
|
|
5835
|
+
tileset: z3.object({
|
|
5836
|
+
total_tiles: z3.number().int().min(1),
|
|
5837
|
+
tile_size: z3.object({ width: z3.number().int().positive(), height: z3.number().int().positive() }).passthrough(),
|
|
5838
|
+
terrain_types: z3.array(z3.string()),
|
|
5839
|
+
tiles: z3.array(TilesetTileSchema).min(1)
|
|
5720
5840
|
}).passthrough(),
|
|
5721
5841
|
usage: UsageSchema
|
|
5722
5842
|
}).passthrough();
|
|
5723
|
-
var IsometricTileSubmitSchema =
|
|
5724
|
-
tile_id:
|
|
5725
|
-
background_job_id:
|
|
5726
|
-
status:
|
|
5843
|
+
var IsometricTileSubmitSchema = z3.object({
|
|
5844
|
+
tile_id: z3.string().min(1),
|
|
5845
|
+
background_job_id: z3.string().min(1),
|
|
5846
|
+
status: z3.literal("processing").default("processing")
|
|
5727
5847
|
}).passthrough();
|
|
5728
|
-
var IsometricTileGetSchema =
|
|
5729
|
-
image:
|
|
5848
|
+
var IsometricTileGetSchema = z3.object({
|
|
5849
|
+
image: z3.object({ base64: z3.string().min(1), format: z3.string().default("png") }).passthrough(),
|
|
5730
5850
|
usage: UsageSchema
|
|
5731
5851
|
}).passthrough();
|
|
5732
|
-
var UiAssetSubmitSchema =
|
|
5733
|
-
ui_asset_id:
|
|
5734
|
-
background_job_id:
|
|
5735
|
-
status:
|
|
5852
|
+
var UiAssetSubmitSchema = z3.object({
|
|
5853
|
+
ui_asset_id: z3.string().min(1),
|
|
5854
|
+
background_job_id: z3.string().min(1),
|
|
5855
|
+
status: z3.string().default("processing"),
|
|
5736
5856
|
usage: UsageSchema
|
|
5737
5857
|
}).passthrough();
|
|
5738
|
-
var UiAssetGetSchema =
|
|
5739
|
-
id:
|
|
5740
|
-
status:
|
|
5741
|
-
image_url:
|
|
5742
|
-
progress_percent:
|
|
5743
|
-
eta_seconds:
|
|
5858
|
+
var UiAssetGetSchema = z3.object({
|
|
5859
|
+
id: z3.string().min(1),
|
|
5860
|
+
status: z3.string().nullable().default(null),
|
|
5861
|
+
image_url: z3.string().nullable().optional(),
|
|
5862
|
+
progress_percent: z3.number().nullable().optional(),
|
|
5863
|
+
eta_seconds: z3.number().nullable().optional()
|
|
5744
5864
|
}).passthrough();
|
|
5745
|
-
var RevisionJobSubmitSchema =
|
|
5746
|
-
background_job_id:
|
|
5747
|
-
status:
|
|
5865
|
+
var RevisionJobSubmitSchema = z3.object({
|
|
5866
|
+
background_job_id: z3.string().min(1),
|
|
5867
|
+
status: z3.string().default("processing")
|
|
5748
5868
|
}).passthrough();
|
|
5749
|
-
var ObjectAnimationGroupSchema =
|
|
5750
|
-
animation_group_id:
|
|
5751
|
-
display_name:
|
|
5752
|
-
description:
|
|
5753
|
-
frame_count:
|
|
5754
|
-
directions:
|
|
5755
|
-
|
|
5756
|
-
direction:
|
|
5757
|
-
storage_urls:
|
|
5758
|
-
created_at:
|
|
5869
|
+
var ObjectAnimationGroupSchema = z3.object({
|
|
5870
|
+
animation_group_id: z3.string().min(1),
|
|
5871
|
+
display_name: z3.string().nullable().default(null),
|
|
5872
|
+
description: z3.string().default(""),
|
|
5873
|
+
frame_count: z3.number().int().default(0),
|
|
5874
|
+
directions: z3.array(
|
|
5875
|
+
z3.object({
|
|
5876
|
+
direction: z3.string(),
|
|
5877
|
+
storage_urls: z3.record(z3.unknown()).default({}),
|
|
5878
|
+
created_at: z3.string()
|
|
5759
5879
|
}).passthrough()
|
|
5760
5880
|
).default([])
|
|
5761
5881
|
}).passthrough();
|
|
5762
|
-
var PixelLabObjectSchema =
|
|
5763
|
-
id:
|
|
5764
|
-
name:
|
|
5765
|
-
state_name:
|
|
5766
|
-
prompt:
|
|
5767
|
-
size:
|
|
5768
|
-
directions:
|
|
5769
|
-
created_at:
|
|
5770
|
-
view:
|
|
5771
|
-
preview_url:
|
|
5772
|
-
rotation_urls:
|
|
5773
|
-
frame_urls:
|
|
5774
|
-
tags:
|
|
5775
|
-
status:
|
|
5776
|
-
progress_percent:
|
|
5777
|
-
eta_seconds:
|
|
5778
|
-
group_id:
|
|
5779
|
-
animations:
|
|
5882
|
+
var PixelLabObjectSchema = z3.object({
|
|
5883
|
+
id: z3.string().min(1),
|
|
5884
|
+
name: z3.string().nullable().default(null),
|
|
5885
|
+
state_name: z3.string().nullable().optional(),
|
|
5886
|
+
prompt: z3.string().default(""),
|
|
5887
|
+
size: z3.object({ width: z3.number().int().positive(), height: z3.number().int().positive() }),
|
|
5888
|
+
directions: z3.number().default(0),
|
|
5889
|
+
created_at: z3.string(),
|
|
5890
|
+
view: z3.string().nullable().default(null),
|
|
5891
|
+
preview_url: z3.string().nullable().optional(),
|
|
5892
|
+
rotation_urls: z3.record(z3.string().nullable()).nullable().optional(),
|
|
5893
|
+
frame_urls: z3.array(z3.string()).nullable().optional(),
|
|
5894
|
+
tags: z3.array(z3.string()).default([]),
|
|
5895
|
+
status: z3.string().nullable().default(null),
|
|
5896
|
+
progress_percent: z3.number().nullable().optional(),
|
|
5897
|
+
eta_seconds: z3.number().nullable().optional(),
|
|
5898
|
+
group_id: z3.string().nullable().optional(),
|
|
5899
|
+
animations: z3.array(ObjectAnimationGroupSchema).default([])
|
|
5900
|
+
}).passthrough();
|
|
5901
|
+
var MapObjectSchema = z3.object({
|
|
5902
|
+
object_id: z3.string().min(1),
|
|
5903
|
+
status: z3.string(),
|
|
5904
|
+
description: z3.string().nullable().default(null),
|
|
5905
|
+
width: z3.number().nullable().default(null),
|
|
5906
|
+
height: z3.number().nullable().default(null),
|
|
5907
|
+
download_url: z3.string().nullable().default(null)
|
|
5780
5908
|
}).passthrough();
|
|
5781
|
-
var
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5909
|
+
var ObjectListSchema = z3.object({ objects: z3.array(PixelLabObjectSchema), total: z3.number().int().min(0) }).passthrough();
|
|
5910
|
+
var PixfluxResponseSchema = z3.object({ image: z3.object({ base64: z3.string().min(1) }).passthrough(), usage: z3.unknown().optional() }).passthrough();
|
|
5911
|
+
var ReduceColorsResponseSchema = z3.object({
|
|
5912
|
+
images: z3.array(z3.object({ base64: z3.string().min(1) }).passthrough()).min(1),
|
|
5913
|
+
palette: z3.object({ base64: z3.string().min(1) }).passthrough(),
|
|
5914
|
+
n_colors: z3.number().int(),
|
|
5915
|
+
usage: z3.unknown().optional()
|
|
5788
5916
|
}).passthrough();
|
|
5789
|
-
var
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
images: z2.array(z2.object({ base64: z2.string().min(1) }).passthrough()).min(1),
|
|
5793
|
-
palette: z2.object({ base64: z2.string().min(1) }).passthrough(),
|
|
5794
|
-
n_colors: z2.number().int(),
|
|
5795
|
-
usage: z2.unknown().optional()
|
|
5917
|
+
var CorrectPixelartResponseSchema = z3.object({
|
|
5918
|
+
images: z3.array(z3.object({ base64: z3.string().min(1) }).passthrough()).min(1),
|
|
5919
|
+
usage: z3.unknown().optional()
|
|
5796
5920
|
}).passthrough();
|
|
5797
|
-
var
|
|
5798
|
-
|
|
5799
|
-
|
|
5921
|
+
var ProFlashImageSubmitSchema = z3.object({
|
|
5922
|
+
background_job_id: z3.string().min(1),
|
|
5923
|
+
image_id: z3.string().min(1),
|
|
5924
|
+
source_image_id: z3.string().min(1),
|
|
5925
|
+
status: z3.string().default("processing"),
|
|
5926
|
+
estimated_generations: z3.number().nullable().optional(),
|
|
5927
|
+
usage: z3.unknown().optional()
|
|
5800
5928
|
}).passthrough();
|
|
5801
|
-
var
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
usage: z2.unknown().optional()
|
|
5929
|
+
var UnzoomResponseSchema = z3.object({
|
|
5930
|
+
image: z3.object({ base64: z3.string().min(1) }).passthrough(),
|
|
5931
|
+
original_size: z3.object({ width: z3.number().int(), height: z3.number().int() }).passthrough(),
|
|
5932
|
+
unzoomed_size: z3.object({ width: z3.number().int(), height: z3.number().int() }).passthrough(),
|
|
5933
|
+
zoom_factor_detected: z3.number(),
|
|
5934
|
+
usage: z3.unknown().optional()
|
|
5808
5935
|
}).passthrough();
|
|
5809
|
-
var
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5936
|
+
var FontJobSchema = z3.object({
|
|
5937
|
+
job_id: z3.string().min(1),
|
|
5938
|
+
status: z3.string(),
|
|
5939
|
+
glyph_px: z3.number().int().nullable().optional(),
|
|
5940
|
+
download_atlas_url: z3.string().nullable().optional(),
|
|
5941
|
+
download_ttf_url: z3.string().nullable().optional(),
|
|
5942
|
+
usage: z3.unknown().optional()
|
|
5815
5943
|
}).passthrough();
|
|
5816
|
-
var
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
download_atlas_url: z2.string().nullable().optional(),
|
|
5821
|
-
download_ttf_url: z2.string().nullable().optional(),
|
|
5822
|
-
usage: z2.unknown().optional()
|
|
5944
|
+
var SelectFramesSchema = z3.object({ created_object_ids: z3.array(z3.string()) }).passthrough();
|
|
5945
|
+
var EstimateSkeletonResponseSchema = z3.object({
|
|
5946
|
+
keypoints: z3.array(SkeletonKeypointSchema).length(18),
|
|
5947
|
+
usage: z3.unknown().optional()
|
|
5823
5948
|
}).passthrough();
|
|
5824
|
-
var
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
status: z2.string().default("processing"),
|
|
5949
|
+
var CharacterSubmitSchema = z3.object({
|
|
5950
|
+
background_job_id: z3.string().min(1),
|
|
5951
|
+
character_id: z3.string().min(1),
|
|
5952
|
+
status: z3.string().default("processing"),
|
|
5829
5953
|
usage: UsageSchema
|
|
5830
5954
|
}).passthrough();
|
|
5831
|
-
var AnimateSubmitSchema =
|
|
5832
|
-
background_job_ids:
|
|
5833
|
-
directions:
|
|
5834
|
-
status:
|
|
5955
|
+
var AnimateSubmitSchema = z3.object({
|
|
5956
|
+
background_job_ids: z3.array(z3.string()),
|
|
5957
|
+
directions: z3.array(z3.string()),
|
|
5958
|
+
status: z3.string().default("processing"),
|
|
5835
5959
|
usage: UsageSchema
|
|
5836
5960
|
}).passthrough();
|
|
5837
|
-
var ObjectProSubmitSchema =
|
|
5838
|
-
object_id:
|
|
5839
|
-
background_job_id:
|
|
5840
|
-
status:
|
|
5961
|
+
var ObjectProSubmitSchema = z3.object({
|
|
5962
|
+
object_id: z3.string().min(1),
|
|
5963
|
+
background_job_id: z3.string().min(1),
|
|
5964
|
+
status: z3.string().default("processing"),
|
|
5841
5965
|
usage: UsageSchema
|
|
5842
5966
|
}).passthrough();
|
|
5843
|
-
var DirectionSubmissionSchema =
|
|
5844
|
-
direction:
|
|
5845
|
-
status:
|
|
5846
|
-
background_job_id:
|
|
5847
|
-
animation_id:
|
|
5967
|
+
var DirectionSubmissionSchema = z3.object({
|
|
5968
|
+
direction: z3.string(),
|
|
5969
|
+
status: z3.string(),
|
|
5970
|
+
background_job_id: z3.string().nullable().default(null),
|
|
5971
|
+
animation_id: z3.string().nullable().default(null)
|
|
5848
5972
|
}).passthrough();
|
|
5849
|
-
var AnimateObjectSubmitSchema =
|
|
5850
|
-
animation_group_id:
|
|
5851
|
-
object_id:
|
|
5852
|
-
mode:
|
|
5853
|
-
frame_count:
|
|
5854
|
-
display_name:
|
|
5855
|
-
description:
|
|
5856
|
-
submissions:
|
|
5973
|
+
var AnimateObjectSubmitSchema = z3.object({
|
|
5974
|
+
animation_group_id: z3.string().min(1),
|
|
5975
|
+
object_id: z3.string().min(1),
|
|
5976
|
+
mode: z3.string(),
|
|
5977
|
+
frame_count: z3.number().int(),
|
|
5978
|
+
display_name: z3.string().nullable().default(null),
|
|
5979
|
+
description: z3.string().default(""),
|
|
5980
|
+
submissions: z3.array(DirectionSubmissionSchema),
|
|
5857
5981
|
usage: UsageSchema
|
|
5858
5982
|
}).passthrough();
|
|
5859
|
-
var PortraitSubmitSchema =
|
|
5860
|
-
background_job_id:
|
|
5861
|
-
status:
|
|
5983
|
+
var PortraitSubmitSchema = z3.object({
|
|
5984
|
+
background_job_id: z3.string().min(1),
|
|
5985
|
+
status: z3.string().default("processing"),
|
|
5862
5986
|
usage: UsageSchema
|
|
5863
5987
|
}).passthrough();
|
|
5864
|
-
var PortraitJobSchema =
|
|
5865
|
-
status:
|
|
5866
|
-
download_url:
|
|
5867
|
-
width:
|
|
5868
|
-
height:
|
|
5988
|
+
var PortraitJobSchema = z3.object({
|
|
5989
|
+
status: z3.string(),
|
|
5990
|
+
download_url: z3.string().nullable().optional(),
|
|
5991
|
+
width: z3.number().int().nullable().optional(),
|
|
5992
|
+
height: z3.number().int().nullable().optional()
|
|
5869
5993
|
}).passthrough();
|
|
5870
|
-
var SetPortraitSchema =
|
|
5871
|
-
character_id:
|
|
5872
|
-
size:
|
|
5873
|
-
url:
|
|
5994
|
+
var SetPortraitSchema = z3.object({
|
|
5995
|
+
character_id: z3.string().min(1),
|
|
5996
|
+
size: z3.number().int().positive(),
|
|
5997
|
+
url: z3.string().min(1),
|
|
5874
5998
|
usage: UsageSchema
|
|
5875
5999
|
}).passthrough();
|
|
5876
|
-
var TransferOutfitSubmitSchema =
|
|
5877
|
-
background_job_id:
|
|
5878
|
-
status:
|
|
6000
|
+
var TransferOutfitSubmitSchema = z3.object({
|
|
6001
|
+
background_job_id: z3.string().min(1),
|
|
6002
|
+
status: z3.string().default("processing"),
|
|
5879
6003
|
usage: UsageSchema
|
|
5880
6004
|
}).passthrough();
|
|
5881
|
-
var CharacterAnimationDirectionSchema =
|
|
5882
|
-
direction:
|
|
5883
|
-
frame_count:
|
|
5884
|
-
frames:
|
|
6005
|
+
var CharacterAnimationDirectionSchema = z3.object({
|
|
6006
|
+
direction: z3.string(),
|
|
6007
|
+
frame_count: z3.number().int().min(0),
|
|
6008
|
+
frames: z3.array(z3.string())
|
|
5885
6009
|
}).passthrough();
|
|
5886
|
-
var CharacterAnimationSchema2 =
|
|
5887
|
-
animation_type:
|
|
5888
|
-
display_name:
|
|
5889
|
-
animation_group_id:
|
|
5890
|
-
directions:
|
|
6010
|
+
var CharacterAnimationSchema2 = z3.object({
|
|
6011
|
+
animation_type: z3.string(),
|
|
6012
|
+
display_name: z3.string().nullable().optional(),
|
|
6013
|
+
animation_group_id: z3.string().nullable().optional(),
|
|
6014
|
+
directions: z3.array(CharacterAnimationDirectionSchema)
|
|
5891
6015
|
}).passthrough();
|
|
5892
|
-
var CharacterSchema =
|
|
5893
|
-
id:
|
|
5894
|
-
name:
|
|
5895
|
-
state_name:
|
|
5896
|
-
prompt:
|
|
5897
|
-
size:
|
|
5898
|
-
directions:
|
|
5899
|
-
created_at:
|
|
5900
|
-
updated_at:
|
|
5901
|
-
animation_count:
|
|
5902
|
-
template_id:
|
|
5903
|
-
view:
|
|
5904
|
-
status:
|
|
5905
|
-
rotation_urls:
|
|
5906
|
-
tags:
|
|
5907
|
-
group_id:
|
|
5908
|
-
animations:
|
|
5909
|
-
preview_url:
|
|
6016
|
+
var CharacterSchema = z3.object({
|
|
6017
|
+
id: z3.string().min(1),
|
|
6018
|
+
name: z3.string().default(""),
|
|
6019
|
+
state_name: z3.string().nullable().optional(),
|
|
6020
|
+
prompt: z3.string().default(""),
|
|
6021
|
+
size: z3.object({ width: z3.number().int().positive(), height: z3.number().int().positive() }),
|
|
6022
|
+
directions: z3.number().int(),
|
|
6023
|
+
created_at: z3.string(),
|
|
6024
|
+
updated_at: z3.string().nullable().optional(),
|
|
6025
|
+
animation_count: z3.number().int().default(0),
|
|
6026
|
+
template_id: z3.string().default("mannequin"),
|
|
6027
|
+
view: z3.string().nullable().optional(),
|
|
6028
|
+
status: z3.string().default("completed"),
|
|
6029
|
+
rotation_urls: z3.record(z3.string().nullable()).nullable().optional(),
|
|
6030
|
+
tags: z3.array(z3.string()).default([]),
|
|
6031
|
+
group_id: z3.string().nullable().optional(),
|
|
6032
|
+
animations: z3.array(CharacterAnimationSchema2).default([]),
|
|
6033
|
+
preview_url: z3.string().nullable().optional()
|
|
5910
6034
|
}).passthrough();
|
|
5911
|
-
var CharacterListSchema =
|
|
5912
|
-
var BackgroundJobSchema =
|
|
5913
|
-
id:
|
|
5914
|
-
status:
|
|
5915
|
-
last_response:
|
|
6035
|
+
var CharacterListSchema = z3.object({ characters: z3.array(CharacterSchema), total: z3.number().int().min(0) }).passthrough();
|
|
6036
|
+
var BackgroundJobSchema = z3.object({
|
|
6037
|
+
id: z3.string(),
|
|
6038
|
+
status: z3.string(),
|
|
6039
|
+
last_response: z3.record(z3.unknown()).nullable().optional(),
|
|
5916
6040
|
/**
|
|
5917
6041
|
* The billed amount, confirmed live for a `map` object and a standard
|
|
5918
6042
|
* character base (docs/ENDPOINTS.md, "Limits and billing"); duplicated at
|
|
@@ -5920,7 +6044,7 @@ var BackgroundJobSchema = z2.object({
|
|
|
5920
6044
|
*/
|
|
5921
6045
|
usage: UsageSchema
|
|
5922
6046
|
}).passthrough();
|
|
5923
|
-
var DeleteAnimationsSchema =
|
|
6047
|
+
var DeleteAnimationsSchema = z3.object({ success: z3.boolean(), deleted_count: z3.number().int().default(0), error: z3.string().nullable().optional() }).passthrough();
|
|
5924
6048
|
function validateResponse(schema, raw, operation) {
|
|
5925
6049
|
const parsed = schema.safeParse(raw);
|
|
5926
6050
|
if (parsed.success) return parsed.data;
|
|
@@ -5966,9 +6090,9 @@ var PixelLabClient = class {
|
|
|
5966
6090
|
apiKey;
|
|
5967
6091
|
http;
|
|
5968
6092
|
/** Retries transport failures, 429, and 5xx; see http.ts for the policy. */
|
|
5969
|
-
async request(
|
|
6093
|
+
async request(path48, init) {
|
|
5970
6094
|
const auth = this.apiKey.startsWith("Bearer ") ? this.apiKey : `Bearer ${this.apiKey}`;
|
|
5971
|
-
const res = await this.http(`${BASE}${
|
|
6095
|
+
const res = await this.http(`${BASE}${path48}`, {
|
|
5972
6096
|
...init,
|
|
5973
6097
|
headers: {
|
|
5974
6098
|
Authorization: auth,
|
|
@@ -5978,13 +6102,13 @@ var PixelLabClient = class {
|
|
|
5978
6102
|
});
|
|
5979
6103
|
const text = await res.text();
|
|
5980
6104
|
if (!res.ok) {
|
|
5981
|
-
throw new PixelLabError(`${init?.method ?? "GET"} ${
|
|
6105
|
+
throw new PixelLabError(`${init?.method ?? "GET"} ${path48} \u2192 ${res.status}`, res.status, text);
|
|
5982
6106
|
}
|
|
5983
6107
|
if (!text) return {};
|
|
5984
6108
|
try {
|
|
5985
6109
|
return JSON.parse(text);
|
|
5986
6110
|
} catch {
|
|
5987
|
-
throw new Error(`${init?.method ?? "GET"} ${
|
|
6111
|
+
throw new Error(`${init?.method ?? "GET"} ${path48} returned invalid JSON`);
|
|
5988
6112
|
}
|
|
5989
6113
|
}
|
|
5990
6114
|
async balance() {
|
|
@@ -6040,6 +6164,12 @@ var PixelLabClient = class {
|
|
|
6040
6164
|
if (args.shading) body.shading = args.shading;
|
|
6041
6165
|
if (args.detail) body.detail = args.detail;
|
|
6042
6166
|
if (args.seed != null) body.seed = args.seed;
|
|
6167
|
+
if (args.scene) {
|
|
6168
|
+
const encode = (image) => ({ type: "base64", base64: image.base64, format: image.format });
|
|
6169
|
+
const placement = args.scene.placement;
|
|
6170
|
+
body.background_image = encode(args.scene.image);
|
|
6171
|
+
body.inpainting = placement.type === "mask" ? { type: "mask", mask_image: encode(placement.mask) } : { type: placement.type, fraction: placement.fraction };
|
|
6172
|
+
}
|
|
6043
6173
|
return validateResponse(
|
|
6044
6174
|
MapSubmitSchema,
|
|
6045
6175
|
await this.request("/map-objects", { method: "POST", body: JSON.stringify(body) }),
|
|
@@ -6370,10 +6500,10 @@ var PixelLabClient = class {
|
|
|
6370
6500
|
const palette = args.paletteSwatchBase64 ? { color_image: { type: "base64", base64: args.paletteSwatchBase64, format: "png" }, force_colors: true } : {};
|
|
6371
6501
|
const encode = (image) => ({ type: "base64", base64: image.base64, format: image.format });
|
|
6372
6502
|
const south = args.reference?.south;
|
|
6373
|
-
let
|
|
6503
|
+
let path48;
|
|
6374
6504
|
let body;
|
|
6375
6505
|
if (args.mode === "v3") {
|
|
6376
|
-
|
|
6506
|
+
path48 = "/create-character-v3";
|
|
6377
6507
|
body = {
|
|
6378
6508
|
description: args.description,
|
|
6379
6509
|
image_size: imageSize,
|
|
@@ -6387,7 +6517,7 @@ var PixelLabClient = class {
|
|
|
6387
6517
|
...args.enhancePrompt ? { enhance_prompt: true } : {}
|
|
6388
6518
|
};
|
|
6389
6519
|
} else if (args.mode === "pro-flash") {
|
|
6390
|
-
|
|
6520
|
+
path48 = "/create-character-pro-flash";
|
|
6391
6521
|
const traits = args.styleTraits;
|
|
6392
6522
|
body = {
|
|
6393
6523
|
description: args.description,
|
|
@@ -6411,7 +6541,7 @@ var PixelLabClient = class {
|
|
|
6411
6541
|
} : {}
|
|
6412
6542
|
};
|
|
6413
6543
|
} else if (args.mode === "pro") {
|
|
6414
|
-
|
|
6544
|
+
path48 = "/create-character-pro";
|
|
6415
6545
|
body = {
|
|
6416
6546
|
description: args.description,
|
|
6417
6547
|
image_size: imageSize,
|
|
@@ -6425,7 +6555,7 @@ var PixelLabClient = class {
|
|
|
6425
6555
|
...!south && args.styleCharacterId ? { style_character_id: args.styleCharacterId } : {}
|
|
6426
6556
|
};
|
|
6427
6557
|
} else {
|
|
6428
|
-
|
|
6558
|
+
path48 = args.directions === 4 ? "/create-character-with-4-directions" : "/create-character-with-8-directions";
|
|
6429
6559
|
body = {
|
|
6430
6560
|
description: args.description,
|
|
6431
6561
|
image_size: imageSize,
|
|
@@ -6442,8 +6572,8 @@ var PixelLabClient = class {
|
|
|
6442
6572
|
...palette
|
|
6443
6573
|
};
|
|
6444
6574
|
}
|
|
6445
|
-
const raw = await this.request(
|
|
6446
|
-
return validateResponse(CharacterSubmitSchema, raw,
|
|
6575
|
+
const raw = await this.request(path48, { method: "POST", body: JSON.stringify(body) });
|
|
6576
|
+
return validateResponse(CharacterSubmitSchema, raw, path48.slice(1));
|
|
6447
6577
|
}
|
|
6448
6578
|
/** A text edit of an existing character, applied to every direction and stored as a sibling. */
|
|
6449
6579
|
async createCharacterState(args) {
|
|
@@ -6951,6 +7081,61 @@ var PixelLabClient = class {
|
|
|
6951
7081
|
"animate-pixminimax"
|
|
6952
7082
|
);
|
|
6953
7083
|
}
|
|
7084
|
+
/**
|
|
7085
|
+
* `/animate-with-skeleton-v3`, beta (tier 1 subscription or higher): poses
|
|
7086
|
+
* one reference image frame-by-frame from a supplied skeleton per frame,
|
|
7087
|
+
* rather than a text motion description. Confirmed against the live
|
|
7088
|
+
* `animate_with_skeleton_v3` MCP tool schema (the same authoritative
|
|
7089
|
+
* source this codebase already treats as ground truth for the
|
|
7090
|
+
* character/object family) — `action`/`description` are both real,
|
|
7091
|
+
* optional wire fields, contrary to an initial guess that this endpoint
|
|
7092
|
+
* took no text input at all; `direction`/`keypoints`/`firstFrameKeypoints`
|
|
7093
|
+
* are required. The example keypoint from that same tool schema,
|
|
7094
|
+
* `{"label": "RIGHT KNEE", "x": 0.52, "y": 0.71, "z_index": 9}`, is what
|
|
7095
|
+
* `SkeletonKeypointSchema` (`src/skeleton.ts`) models. Same
|
|
7096
|
+
* unverified-completed-shape caveat as `animateWithTextV3`/
|
|
7097
|
+
* `animatePixminimax` above — this endpoint has never been called against
|
|
7098
|
+
* a live account by this codebase.
|
|
7099
|
+
*/
|
|
7100
|
+
async animateWithSkeletonV3(args) {
|
|
7101
|
+
const body = {
|
|
7102
|
+
first_frame: args.firstFrame,
|
|
7103
|
+
first_frame_keypoints: args.firstFrameKeypoints,
|
|
7104
|
+
keypoints: args.keypoints,
|
|
7105
|
+
direction: args.direction
|
|
7106
|
+
};
|
|
7107
|
+
if (args.templateId) body.template_id = args.templateId;
|
|
7108
|
+
if (args.action) body.action = args.action;
|
|
7109
|
+
if (args.description) body.description = args.description;
|
|
7110
|
+
if (args.seed != null) body.seed = args.seed;
|
|
7111
|
+
if (args.noBackground != null) body.no_background = args.noBackground;
|
|
7112
|
+
return validateResponse(
|
|
7113
|
+
RevisionJobSubmitSchema,
|
|
7114
|
+
await this.request("/animate-with-skeleton-v3", { method: "POST", body: JSON.stringify(body) }),
|
|
7115
|
+
"animate-with-skeleton-v3"
|
|
7116
|
+
);
|
|
7117
|
+
}
|
|
7118
|
+
/**
|
|
7119
|
+
* `/estimate-skeleton`: auto-derives a reference image's own 18-joint
|
|
7120
|
+
* keypoints, directly usable as `animateWithSkeletonV3`'s
|
|
7121
|
+
* `firstFrameKeypoints` (or, run against a candidate pose image, as one
|
|
7122
|
+
* entry of its `keypoints` sequence). Not called anywhere in this
|
|
7123
|
+
* codebase's own submit/poll pipeline — deliberately kept outside it (see
|
|
7124
|
+
* `runEstimateSkeleton` in `src/cli/commands`) so the only PixelLab
|
|
7125
|
+
* endpoint composed into `animate-with-skeleton-v3`'s submission is that
|
|
7126
|
+
* one endpoint itself, not two unverified calls chained together.
|
|
7127
|
+
* Synchronous per this endpoint's own framing; unverified against a live
|
|
7128
|
+
* account (see `EstimateSkeletonResponseSchema`'s own caveat).
|
|
7129
|
+
*/
|
|
7130
|
+
async estimateSkeleton(args) {
|
|
7131
|
+
const body = { image: args.image };
|
|
7132
|
+
const res = validateResponse(
|
|
7133
|
+
EstimateSkeletonResponseSchema,
|
|
7134
|
+
await this.request("/estimate-skeleton", { method: "POST", body: JSON.stringify(body) }),
|
|
7135
|
+
"estimate-skeleton"
|
|
7136
|
+
);
|
|
7137
|
+
return { keypoints: res.keypoints, usage: res.usage };
|
|
7138
|
+
}
|
|
6954
7139
|
async getBackgroundJob(jobId) {
|
|
6955
7140
|
const raw = await this.request(`/background-jobs/${encodeURIComponent(jobId)}`);
|
|
6956
7141
|
return validateResponse(BackgroundJobSchema, raw, "background-jobs/{id}");
|
|
@@ -7084,6 +7269,18 @@ function objectProCost(spec) {
|
|
|
7084
7269
|
const south = object.reference;
|
|
7085
7270
|
return south ? proFlashObjectCost(south.width, south.height, object.directions, true) : proFlashObjectCost(spec.width, spec.height, object.directions, false);
|
|
7086
7271
|
}
|
|
7272
|
+
function animateSkeletonCost(frames) {
|
|
7273
|
+
const anchors = [[3, 2], [8, 3], [15, 4]];
|
|
7274
|
+
for (let i = 0; i < anchors.length - 1; i++) {
|
|
7275
|
+
const [lowFrames, lowCost] = anchors[i];
|
|
7276
|
+
const [highFrames, highCost] = anchors[i + 1];
|
|
7277
|
+
if (frames >= lowFrames && frames <= highFrames) {
|
|
7278
|
+
const t = (frames - lowFrames) / (highFrames - lowFrames);
|
|
7279
|
+
return lowCost + t * (highCost - lowCost);
|
|
7280
|
+
}
|
|
7281
|
+
}
|
|
7282
|
+
return frames <= anchors[0][0] ? anchors[0][1] : anchors[anchors.length - 1][1];
|
|
7283
|
+
}
|
|
7087
7284
|
var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
|
|
7088
7285
|
var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
|
|
7089
7286
|
function encodeAnimationJob(job) {
|
|
@@ -7134,6 +7331,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7134
7331
|
supports(generator) {
|
|
7135
7332
|
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";
|
|
7136
7333
|
}
|
|
7334
|
+
/** `/map-objects` style matching: `background_image` plus `inpainting`. */
|
|
7335
|
+
supportsMapScene = true;
|
|
7137
7336
|
/**
|
|
7138
7337
|
* `inpaint` (`/inpaint-v3`, a mask) and `image-to-image` (`/edit-images-v2`,
|
|
7139
7338
|
* no mask) both exist on PixelLab, and so do `reduce-colors`
|
|
@@ -7142,7 +7341,9 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7142
7341
|
* rather than a described edit — and `animate`/`animate-pixminimax`
|
|
7143
7342
|
* (`/animate-with-text-v3`, `/animate-pixminimax`), which animate any loose
|
|
7144
7343
|
* image from a text description with no character/object resource
|
|
7145
|
-
* required —
|
|
7344
|
+
* required — `animate-skeleton` (`/animate-with-skeleton-v3`, posing the
|
|
7345
|
+
* source from a supplied per-frame skeleton instead of a text description)
|
|
7346
|
+
* — and `interpolate` (`/interpolation-v2`, the in-betweens
|
|
7146
7347
|
* from one keyframe to another) and `edit-animation`
|
|
7147
7348
|
* (`/edit-animation-v2`, one text edit applied across a whole frame set).
|
|
7148
7349
|
* `outpaint` does not: there is no canvas-expansion endpoint in the API,
|
|
@@ -7150,7 +7351,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7150
7351
|
* outpaint path yet.
|
|
7151
7352
|
*/
|
|
7152
7353
|
supportsRevision(mode2) {
|
|
7153
|
-
return mode2 === "inpaint" || mode2 === "image-to-image" || mode2 === "reduce-colors" || mode2 === "correct-pixelart" || mode2 === "animate" || mode2 === "animate-pixminimax" || mode2 === "interpolate" || mode2 === "edit-animation";
|
|
7354
|
+
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";
|
|
7154
7355
|
}
|
|
7155
7356
|
/** PixelLab's own constraints: submissions must be >2s apart, and
|
|
7156
7357
|
* background jobs in flight are capped by subscription tier (Tier 1=8,
|
|
@@ -7181,6 +7382,10 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7181
7382
|
if (spec.revision?.mode === "reduce-colors" || spec.revision?.mode === "correct-pixelart") {
|
|
7182
7383
|
return { unit: "generations", amount: 0.1, candidates: 1 };
|
|
7183
7384
|
}
|
|
7385
|
+
if (spec.revision?.mode === "animate-skeleton") {
|
|
7386
|
+
const frames = spec.revision.frames ?? 8;
|
|
7387
|
+
return { unit: "generations", amount: Math.ceil(animateSkeletonCost(frames)), candidates: 1 };
|
|
7388
|
+
}
|
|
7184
7389
|
if (spec.revision?.mode === "interpolate" || spec.revision?.mode === "edit-animation") {
|
|
7185
7390
|
const width = spec.revision.sourceWidth ?? spec.width;
|
|
7186
7391
|
const height = spec.revision.sourceHeight ?? spec.height;
|
|
@@ -7262,6 +7467,18 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7262
7467
|
throw new Error(`PixelLab correct-pixelart source is ${width}x${height}; the API takes at most 1024 pixels per side`);
|
|
7263
7468
|
}
|
|
7264
7469
|
}
|
|
7470
|
+
if (spec.revision?.mode === "animate-skeleton") {
|
|
7471
|
+
const { sourceWidth: width, sourceHeight: height, frames, skeletonTemplate } = spec.revision;
|
|
7472
|
+
if (width != null && height != null && (width > 256 || height > 256)) {
|
|
7473
|
+
throw new Error(`PixelLab animate-skeleton source is ${width}x${height}; the API takes at most 256 pixels per side`);
|
|
7474
|
+
}
|
|
7475
|
+
if (frames != null && (frames < 3 || frames > 15)) {
|
|
7476
|
+
throw new Error(`PixelLab animate-skeleton takes 3 to 15 frames; the keypoints file has ${frames}`);
|
|
7477
|
+
}
|
|
7478
|
+
if (skeletonTemplate && !CHARACTER_TEMPLATES.includes(skeletonTemplate)) {
|
|
7479
|
+
throw new Error(`PixelLab animate-skeleton template "${skeletonTemplate}" is not one of ${CHARACTER_TEMPLATES.join(", ")}`);
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7265
7482
|
if (spec.revision?.mode === "animate" || spec.revision?.mode === "animate-pixminimax") {
|
|
7266
7483
|
const { sourceWidth: width, sourceHeight: height, mode: mode2, frames, lastFrameWidth, lastFrameHeight } = spec.revision;
|
|
7267
7484
|
if (width != null && height != null && (width > 256 || height > 256)) {
|
|
@@ -8261,7 +8478,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
8261
8478
|
outline: spec.outline,
|
|
8262
8479
|
shading: spec.shading,
|
|
8263
8480
|
detail: spec.detail,
|
|
8264
|
-
seed: spec.seed
|
|
8481
|
+
seed: spec.seed,
|
|
8482
|
+
scene: spec.scene ? mapScenePayload(spec) : void 0
|
|
8265
8483
|
});
|
|
8266
8484
|
return { jobId: res.object_id, metadata: { backgroundJobId: res.background_job_id } };
|
|
8267
8485
|
}
|
|
@@ -8411,6 +8629,27 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
8411
8629
|
});
|
|
8412
8630
|
return { jobId: res2.background_job_id };
|
|
8413
8631
|
}
|
|
8632
|
+
if (revision.mode === "animate-skeleton") {
|
|
8633
|
+
if (!revision.keypointsFile || !revision.keypointsSha256 || !revision.skeleton) {
|
|
8634
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: revision keypoints are not ready`);
|
|
8635
|
+
}
|
|
8636
|
+
const keypointsBytes = readFileSync2(revision.keypointsFile);
|
|
8637
|
+
if (sha256(keypointsBytes) !== revision.keypointsSha256) {
|
|
8638
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: revision keypoints changed after the manifest was resolved`);
|
|
8639
|
+
}
|
|
8640
|
+
const res2 = await this.client.animateWithSkeletonV3({
|
|
8641
|
+
firstFrame: image,
|
|
8642
|
+
firstFrameKeypoints: revision.skeleton.firstFrameKeypoints,
|
|
8643
|
+
keypoints: revision.skeleton.frames,
|
|
8644
|
+
direction: revision.direction,
|
|
8645
|
+
templateId: revision.skeletonTemplate,
|
|
8646
|
+
action: spec.prompt,
|
|
8647
|
+
description: revision.description,
|
|
8648
|
+
seed: spec.seed,
|
|
8649
|
+
noBackground: spec.noBackground
|
|
8650
|
+
});
|
|
8651
|
+
return { jobId: res2.background_job_id };
|
|
8652
|
+
}
|
|
8414
8653
|
if (revision.strength != null) {
|
|
8415
8654
|
throw new Error(
|
|
8416
8655
|
`${spec.styleId}/${spec.assetId}: PixelLab image-to-image revisions take no strength; edit-images-v2 always applies the full instruction`
|
|
@@ -8476,7 +8715,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
8476
8715
|
if (revisionMode === "reduce-colors" || revisionMode === "correct-pixelart") {
|
|
8477
8716
|
return this.pollCachedRevision(jobId, context);
|
|
8478
8717
|
}
|
|
8479
|
-
if (revisionMode === "animate" || revisionMode === "animate-pixminimax" || revisionMode === "interpolate" || revisionMode === "edit-animation") {
|
|
8718
|
+
if (revisionMode === "animate" || revisionMode === "animate-pixminimax" || revisionMode === "animate-skeleton" || revisionMode === "interpolate" || revisionMode === "edit-animation") {
|
|
8480
8719
|
return this.pollAnimateRevision(jobId, context);
|
|
8481
8720
|
}
|
|
8482
8721
|
if (context?.spec?.revision) return this.pollRevision(jobId);
|
|
@@ -9117,6 +9356,21 @@ function findObjectAnimation(object, name, direction, animationId) {
|
|
|
9117
9356
|
}
|
|
9118
9357
|
return null;
|
|
9119
9358
|
}
|
|
9359
|
+
function mapScenePayload(spec) {
|
|
9360
|
+
const scene = spec.scene;
|
|
9361
|
+
const read = (file, hash, label) => {
|
|
9362
|
+
const bytes = readFileSync2(file);
|
|
9363
|
+
if (!hash || sha256(bytes) !== hash) {
|
|
9364
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: ${label} changed after the manifest was resolved`);
|
|
9365
|
+
}
|
|
9366
|
+
return { base64: bytes.toString("base64"), format: "png" };
|
|
9367
|
+
};
|
|
9368
|
+
const placement = scene.placement;
|
|
9369
|
+
return {
|
|
9370
|
+
image: read(scene.file, scene.sha256, "scene image"),
|
|
9371
|
+
placement: placement.type === "mask" ? { type: "mask", mask: read(placement.file, placement.sha256, "scene mask") } : placement
|
|
9372
|
+
};
|
|
9373
|
+
}
|
|
9120
9374
|
|
|
9121
9375
|
// src/providers/retrodiffusion.ts
|
|
9122
9376
|
var DEFAULT_BASE_URL2 = "https://api.retrodiffusion.ai/v1";
|
|
@@ -9166,9 +9420,9 @@ var RetroDiffusionClient = class {
|
|
|
9166
9420
|
if (!response.ok) throw new ProviderError("retrodiffusion", `Retro Diffusion download failed (${response.status})`, { status: response.status });
|
|
9167
9421
|
return Buffer.from(await response.arrayBuffer());
|
|
9168
9422
|
}
|
|
9169
|
-
async call(
|
|
9423
|
+
async call(path48, init = {}) {
|
|
9170
9424
|
if (!this.token) throw new Error("RD_API_KEY is not set");
|
|
9171
|
-
const response = await this.request(`${this.baseUrl}${
|
|
9425
|
+
const response = await this.request(`${this.baseUrl}${path48}`, {
|
|
9172
9426
|
...init,
|
|
9173
9427
|
headers: {
|
|
9174
9428
|
"Content-Type": "application/json",
|
|
@@ -10712,6 +10966,8 @@ async function resolveSpecs(loaded, filter) {
|
|
|
10712
10966
|
const paletteImage = paletteImageFile ? await optionalRevisionImage(paletteImageFile, "revision palette image", "png") : null;
|
|
10713
10967
|
const lastFrameFile = asset.revision.lastFrame ? path13.resolve(root, asset.revision.lastFrame) : void 0;
|
|
10714
10968
|
const lastFrame = lastFrameFile ? await optionalRevisionImage(lastFrameFile, "revision last frame") : null;
|
|
10969
|
+
const keypointsFile = asset.revision.keypointsFile ? path13.resolve(root, asset.revision.keypointsFile) : void 0;
|
|
10970
|
+
const keypoints = keypointsFile ? await optionalSkeletonSet(keypointsFile) : null;
|
|
10715
10971
|
resolved.revision = {
|
|
10716
10972
|
mode: asset.revision.mode,
|
|
10717
10973
|
sourceAssetId: asset.revision.from,
|
|
@@ -10752,6 +11008,18 @@ async function resolveSpecs(loaded, filter) {
|
|
|
10752
11008
|
} : {},
|
|
10753
11009
|
...asset.revision.direction ? { direction: asset.revision.direction } : {},
|
|
10754
11010
|
...asset.revision.enhancePrompt == null ? {} : { enhancePrompt: asset.revision.enhancePrompt },
|
|
11011
|
+
...keypointsFile ? {
|
|
11012
|
+
keypointsFile,
|
|
11013
|
+
keypointsSha256: keypoints?.hash ?? null,
|
|
11014
|
+
skeleton: keypoints?.skeleton ?? null,
|
|
11015
|
+
// The manifest's own `frames` field stays rejected for this
|
|
11016
|
+
// mode (superRefine, types.ts) — the real frame count comes
|
|
11017
|
+
// from the keypoints file once it exists, not a manifest
|
|
11018
|
+
// number, so plan can only know it once authored.
|
|
11019
|
+
...keypoints ? { frames: keypoints.skeleton.frames.length } : {}
|
|
11020
|
+
} : {},
|
|
11021
|
+
...asset.revision.skeletonTemplate ? { skeletonTemplate: asset.revision.skeletonTemplate } : {},
|
|
11022
|
+
...asset.revision.description ? { description: asset.revision.description } : {},
|
|
10755
11023
|
...asset.revision.engine ? { engine: asset.revision.engine } : {}
|
|
10756
11024
|
};
|
|
10757
11025
|
}
|
|
@@ -10805,6 +11073,7 @@ async function resolveSpecs(loaded, filter) {
|
|
|
10805
11073
|
};
|
|
10806
11074
|
}
|
|
10807
11075
|
}
|
|
11076
|
+
if (asset.scene) resolved.scene = await resolveMapScene(root, styleId, assetId, resolved.generator, asset.scene, activeProvider);
|
|
10808
11077
|
resolved.specHash = specHash(
|
|
10809
11078
|
resolved,
|
|
10810
11079
|
styleImageHashes,
|
|
@@ -10863,6 +11132,32 @@ function pngPath(file) {
|
|
|
10863
11132
|
const extension = path13.extname(file);
|
|
10864
11133
|
return extension ? `${file.slice(0, -extension.length)}.png` : `${file}.png`;
|
|
10865
11134
|
}
|
|
11135
|
+
async function resolveMapScene(root, styleId, assetId, generator, scene, provider) {
|
|
11136
|
+
if (generator !== "map") {
|
|
11137
|
+
throw new Error(`assets.${assetId}.scene: only a map object can be drawn into a scene; style "${styleId}" uses "${generator}"`);
|
|
11138
|
+
}
|
|
11139
|
+
if (!provider.supportsMapScene) {
|
|
11140
|
+
throw new Error(`assets.${assetId}.scene: provider "${provider.id}" cannot draw into a scene; PixelLab's /map-objects can`);
|
|
11141
|
+
}
|
|
11142
|
+
const file = path13.resolve(root, scene.image);
|
|
11143
|
+
const image = await optionalRevisionImage(file, "scene image", "png");
|
|
11144
|
+
const base = { file, sha256: image?.hash ?? null, width: image?.width ?? null, height: image?.height ?? null };
|
|
11145
|
+
const placement = scene.placement;
|
|
11146
|
+
if ("mask" in placement) {
|
|
11147
|
+
const maskFile = path13.resolve(root, placement.mask);
|
|
11148
|
+
const mask = await optionalRevisionImage(maskFile, "scene mask", "png");
|
|
11149
|
+
if (image && mask && (image.width !== mask.width || image.height !== mask.height)) {
|
|
11150
|
+
throw new Error(
|
|
11151
|
+
`assets.${assetId}.scene: the mask is ${mask.width}x${mask.height}; the scene ${scene.image} is ${image.width}x${image.height}`
|
|
11152
|
+
);
|
|
11153
|
+
}
|
|
11154
|
+
return {
|
|
11155
|
+
...base,
|
|
11156
|
+
placement: { type: "mask", file: maskFile, sha256: mask?.hash ?? null, width: mask?.width ?? null, height: mask?.height ?? null }
|
|
11157
|
+
};
|
|
11158
|
+
}
|
|
11159
|
+
return "oval" in placement ? { ...base, placement: { type: "oval", fraction: placement.oval } } : { ...base, placement: { type: "rectangle", fraction: placement.rectangle } };
|
|
11160
|
+
}
|
|
10866
11161
|
async function optionalRevisionImage(file, label, requiredFormat) {
|
|
10867
11162
|
if (!existsSync8(file)) return null;
|
|
10868
11163
|
const bytes = await readFile6(file);
|
|
@@ -10873,6 +11168,17 @@ async function optionalRevisionImage(file, label, requiredFormat) {
|
|
|
10873
11168
|
}
|
|
10874
11169
|
return { hash: sha256(bytes), ...metadata };
|
|
10875
11170
|
}
|
|
11171
|
+
async function optionalSkeletonSet(file) {
|
|
11172
|
+
if (!existsSync8(file)) return null;
|
|
11173
|
+
const bytes = await readFile6(file);
|
|
11174
|
+
let json;
|
|
11175
|
+
try {
|
|
11176
|
+
json = JSON.parse(bytes.toString("utf8"));
|
|
11177
|
+
} catch (error) {
|
|
11178
|
+
throw new Error(`revision keypoints file ${file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
11179
|
+
}
|
|
11180
|
+
return { hash: sha256(bytes), skeleton: parseSkeletonSet(json, file) };
|
|
11181
|
+
}
|
|
10876
11182
|
async function revisionSourceMembers(stem, label) {
|
|
10877
11183
|
if (existsSync8(stem)) return null;
|
|
10878
11184
|
const at = (role) => memberPath(stem, role, 0, 2, MediaType.PNG);
|
|
@@ -11408,11 +11714,11 @@ import path15 from "path";
|
|
|
11408
11714
|
import { mkdir as mkdir5, readFile as readFile8, rename as rename5, rm as rm5, writeFile as writeFile5 } from "fs/promises";
|
|
11409
11715
|
import { existsSync as existsSync10 } from "fs";
|
|
11410
11716
|
import pathModule from "path";
|
|
11411
|
-
import { z as
|
|
11412
|
-
var HashCacheSchema =
|
|
11413
|
-
version:
|
|
11717
|
+
import { z as z4 } from "zod";
|
|
11718
|
+
var HashCacheSchema = z4.object({
|
|
11719
|
+
version: z4.literal(1),
|
|
11414
11720
|
/** objectId → sha256 of that object's image bytes. */
|
|
11415
|
-
hashes:
|
|
11721
|
+
hashes: z4.record(z4.string())
|
|
11416
11722
|
});
|
|
11417
11723
|
var SHA256_HEX = /^[a-f0-9]{64}$/;
|
|
11418
11724
|
function isSha256Hash(value) {
|
|
@@ -11421,10 +11727,10 @@ function isSha256Hash(value) {
|
|
|
11421
11727
|
function parseCache(value) {
|
|
11422
11728
|
return HashCacheSchema.parse(value);
|
|
11423
11729
|
}
|
|
11424
|
-
async function loadCache(
|
|
11425
|
-
if (!existsSync10(
|
|
11730
|
+
async function loadCache(path48) {
|
|
11731
|
+
if (!existsSync10(path48)) return { version: 1, hashes: {} };
|
|
11426
11732
|
try {
|
|
11427
|
-
const parsed = HashCacheSchema.safeParse(JSON.parse(await readFile8(
|
|
11733
|
+
const parsed = HashCacheSchema.safeParse(JSON.parse(await readFile8(path48, "utf8")));
|
|
11428
11734
|
if (!parsed.success) return { version: 1, hashes: {} };
|
|
11429
11735
|
return {
|
|
11430
11736
|
version: 1,
|
|
@@ -11436,18 +11742,18 @@ async function loadCache(path47) {
|
|
|
11436
11742
|
return { version: 1, hashes: {} };
|
|
11437
11743
|
}
|
|
11438
11744
|
}
|
|
11439
|
-
async function saveCache(
|
|
11745
|
+
async function saveCache(path48, cache) {
|
|
11440
11746
|
const sorted = {};
|
|
11441
11747
|
for (const key of Object.keys(cache.hashes).sort()) {
|
|
11442
11748
|
const hash = cache.hashes[key];
|
|
11443
11749
|
if (!isSha256Hash(hash)) throw new Error(`Refusing to cache invalid SHA-256 for ${key}`);
|
|
11444
11750
|
sorted[key] = hash;
|
|
11445
11751
|
}
|
|
11446
|
-
await mkdir5(pathModule.dirname(pathModule.resolve(
|
|
11447
|
-
const tmp = `${
|
|
11752
|
+
await mkdir5(pathModule.dirname(pathModule.resolve(path48)), { recursive: true });
|
|
11753
|
+
const tmp = `${path48}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
11448
11754
|
try {
|
|
11449
11755
|
await writeFile5(tmp, JSON.stringify({ version: 1, hashes: sorted }, null, 2) + "\n");
|
|
11450
|
-
await rename5(tmp,
|
|
11756
|
+
await rename5(tmp, path48);
|
|
11451
11757
|
} finally {
|
|
11452
11758
|
await rm5(tmp, { force: true });
|
|
11453
11759
|
}
|
|
@@ -12205,20 +12511,20 @@ async function applyTags(provider, decisions, existing, opts = {}) {
|
|
|
12205
12511
|
import { mkdir as mkdir7, readFile as readFile12, rename as rename6, rm as rm6, writeFile as writeFile8 } from "fs/promises";
|
|
12206
12512
|
import { existsSync as existsSync14 } from "fs";
|
|
12207
12513
|
import path18 from "path";
|
|
12208
|
-
import { z as
|
|
12209
|
-
var WorkspaceProjectSchema =
|
|
12210
|
-
id:
|
|
12514
|
+
import { z as z5 } from "zod";
|
|
12515
|
+
var WorkspaceProjectSchema = z5.object({
|
|
12516
|
+
id: z5.string().min(1),
|
|
12211
12517
|
/** Manifest path, relative to the catalog file's own directory. */
|
|
12212
|
-
manifest:
|
|
12518
|
+
manifest: z5.string().min(1),
|
|
12213
12519
|
/** Lockfile path, relative to the catalog file's own directory. */
|
|
12214
|
-
lock:
|
|
12215
|
-
provider:
|
|
12520
|
+
lock: z5.string().min(1),
|
|
12521
|
+
provider: z5.string().min(1).default("pixellab"),
|
|
12216
12522
|
/** Free-form label for a shared account, e.g. distinguishing sandboxes. */
|
|
12217
|
-
account:
|
|
12523
|
+
account: z5.string().optional()
|
|
12218
12524
|
}).strict();
|
|
12219
|
-
var WorkspaceSchema =
|
|
12220
|
-
version:
|
|
12221
|
-
projects:
|
|
12525
|
+
var WorkspaceSchema = z5.object({
|
|
12526
|
+
version: z5.literal(1),
|
|
12527
|
+
projects: z5.array(WorkspaceProjectSchema).default([])
|
|
12222
12528
|
}).strict();
|
|
12223
12529
|
function parseWorkspace(raw) {
|
|
12224
12530
|
const parsed = WorkspaceSchema.safeParse(raw);
|
|
@@ -13403,62 +13709,62 @@ import path25 from "path";
|
|
|
13403
13709
|
import { existsSync as existsSync17 } from "fs";
|
|
13404
13710
|
import { copyFile, mkdir as mkdir9, readFile as readFile16, rename as rename8, rm as rm8, writeFile as writeFile11 } from "fs/promises";
|
|
13405
13711
|
import path24 from "path";
|
|
13406
|
-
import { z as
|
|
13712
|
+
import { z as z7 } from "zod";
|
|
13407
13713
|
|
|
13408
13714
|
// src/manifest-edit.ts
|
|
13409
13715
|
import { readFile as readFile15, rename as rename7, rm as rm7, writeFile as writeFile10 } from "fs/promises";
|
|
13410
13716
|
import path23 from "path";
|
|
13411
|
-
import { z as
|
|
13412
|
-
var HexSha =
|
|
13413
|
-
var AssetPatchSchema =
|
|
13414
|
-
prompt:
|
|
13717
|
+
import { z as z6 } from "zod";
|
|
13718
|
+
var HexSha = z6.string().regex(/^[0-9a-f]{64}$/);
|
|
13719
|
+
var AssetPatchSchema = z6.object({
|
|
13720
|
+
prompt: z6.string().optional(),
|
|
13415
13721
|
/** Per-style override for the style being viewed; null removes it. */
|
|
13416
|
-
promptForStyle:
|
|
13417
|
-
category:
|
|
13418
|
-
width:
|
|
13419
|
-
height:
|
|
13420
|
-
size:
|
|
13421
|
-
tags:
|
|
13722
|
+
promptForStyle: z6.object({ styleId: z6.string().min(1), prompt: z6.string().nullable() }).optional(),
|
|
13723
|
+
category: z6.string().nullable().optional(),
|
|
13724
|
+
width: z6.number().int().nullable().optional(),
|
|
13725
|
+
height: z6.number().int().nullable().optional(),
|
|
13726
|
+
size: z6.number().int().nullable().optional(),
|
|
13727
|
+
tags: z6.array(z6.string()).optional()
|
|
13422
13728
|
}).strict();
|
|
13423
|
-
var NewStateSchema =
|
|
13729
|
+
var NewStateSchema = z6.object({
|
|
13424
13730
|
/** Asset id of the parent this states; must already exist. */
|
|
13425
|
-
of:
|
|
13426
|
-
paletteFromReference:
|
|
13427
|
-
canvas:
|
|
13731
|
+
of: z6.string().min(1),
|
|
13732
|
+
paletteFromReference: z6.boolean().optional(),
|
|
13733
|
+
canvas: z6.object({ width: z6.number().int().min(16).max(256), height: z6.number().int().min(16).max(256) }).strict().optional()
|
|
13428
13734
|
}).strict();
|
|
13429
|
-
var NewAnimationSchema =
|
|
13735
|
+
var NewAnimationSchema = z6.object({
|
|
13430
13736
|
/** Asset id of the parent this animates; must already exist. */
|
|
13431
|
-
of:
|
|
13737
|
+
of: z6.string().min(1),
|
|
13432
13738
|
/** A PixelLab template id (`character` only; `objectPro` has no template concept). */
|
|
13433
|
-
template:
|
|
13739
|
+
template: z6.string().min(1).optional(),
|
|
13434
13740
|
direction: CharacterDirectionSchema.optional(),
|
|
13435
|
-
frames:
|
|
13436
|
-
fps:
|
|
13741
|
+
frames: z6.number().int().min(4).max(16).optional(),
|
|
13742
|
+
fps: z6.number().int().min(1).max(60).optional(),
|
|
13437
13743
|
mode: CharacterAnimationModeSchema.optional(),
|
|
13438
13744
|
/** What is being animated, when the parent's own description would mislead the model (`character` only). */
|
|
13439
|
-
subject:
|
|
13440
|
-
enhancePrompt:
|
|
13745
|
+
subject: z6.string().min(1).optional(),
|
|
13746
|
+
enhancePrompt: z6.boolean().optional()
|
|
13441
13747
|
}).strict();
|
|
13442
|
-
var NewAssetSchema =
|
|
13443
|
-
prompt:
|
|
13444
|
-
category:
|
|
13445
|
-
width:
|
|
13446
|
-
height:
|
|
13447
|
-
size:
|
|
13448
|
-
tags:
|
|
13748
|
+
var NewAssetSchema = z6.object({
|
|
13749
|
+
prompt: z6.string(),
|
|
13750
|
+
category: z6.string().optional(),
|
|
13751
|
+
width: z6.number().int().optional(),
|
|
13752
|
+
height: z6.number().int().optional(),
|
|
13753
|
+
size: z6.number().int().optional(),
|
|
13754
|
+
tags: z6.array(z6.string()).optional(),
|
|
13449
13755
|
/** Restrict to these styles; empty or omitted means every style. */
|
|
13450
|
-
styles:
|
|
13756
|
+
styles: z6.array(z6.string().min(1)).optional(),
|
|
13451
13757
|
/**
|
|
13452
13758
|
* A controlled regeneration of another asset in the same manifest,
|
|
13453
13759
|
* instead of a fresh generation. `inpaint` needs a mask upload the
|
|
13454
13760
|
* gallery does not offer yet, so only `image-to-image` can be created
|
|
13455
13761
|
* here; hand-edit the manifest for the other modes.
|
|
13456
13762
|
*/
|
|
13457
|
-
revision:
|
|
13458
|
-
mode:
|
|
13763
|
+
revision: z6.object({
|
|
13764
|
+
mode: z6.literal("image-to-image"),
|
|
13459
13765
|
/** Asset id of the parent this revises; must already exist. */
|
|
13460
|
-
from:
|
|
13461
|
-
strength:
|
|
13766
|
+
from: z6.string().min(1),
|
|
13767
|
+
strength: z6.number().min(0).max(1).optional()
|
|
13462
13768
|
}).strict().optional(),
|
|
13463
13769
|
/** A pose or outfit of an existing `character`/`objectPro` base or state. */
|
|
13464
13770
|
state: NewStateSchema.optional(),
|
|
@@ -13474,58 +13780,58 @@ var CANDIDATE_OPTION = {
|
|
|
13474
13780
|
comfyui: "numImages",
|
|
13475
13781
|
scenario: "numOutputs"
|
|
13476
13782
|
};
|
|
13477
|
-
var ManifestEditSchema =
|
|
13478
|
-
|
|
13479
|
-
action:
|
|
13783
|
+
var ManifestEditSchema = z6.discriminatedUnion("action", [
|
|
13784
|
+
z6.object({
|
|
13785
|
+
action: z6.literal("patch-asset"),
|
|
13480
13786
|
/** Workspace project id; omitted for a single-project gallery. */
|
|
13481
|
-
project:
|
|
13482
|
-
assetId:
|
|
13787
|
+
project: z6.string().min(1).optional(),
|
|
13788
|
+
assetId: z6.string().min(1),
|
|
13483
13789
|
/** Manifest bytes the page last saw; a mismatch refuses the write. */
|
|
13484
13790
|
expectedSha256: HexSha,
|
|
13485
13791
|
patch: AssetPatchSchema
|
|
13486
13792
|
}).strict(),
|
|
13487
|
-
|
|
13488
|
-
action:
|
|
13489
|
-
project:
|
|
13490
|
-
assetId:
|
|
13793
|
+
z6.object({
|
|
13794
|
+
action: z6.literal("add-asset"),
|
|
13795
|
+
project: z6.string().min(1).optional(),
|
|
13796
|
+
assetId: z6.string().min(1).regex(/^[^/\\]+$/, "asset ids cannot contain slashes"),
|
|
13491
13797
|
expectedSha256: HexSha,
|
|
13492
13798
|
asset: NewAssetSchema
|
|
13493
13799
|
}).strict(),
|
|
13494
|
-
|
|
13495
|
-
action:
|
|
13496
|
-
project:
|
|
13497
|
-
assetId:
|
|
13498
|
-
styleId:
|
|
13800
|
+
z6.object({
|
|
13801
|
+
action: z6.literal("set-source"),
|
|
13802
|
+
project: z6.string().min(1).optional(),
|
|
13803
|
+
assetId: z6.string().min(1),
|
|
13804
|
+
styleId: z6.string().min(1),
|
|
13499
13805
|
/** Manifest-relative path of the art that stands in for this asset in this style. */
|
|
13500
|
-
source:
|
|
13806
|
+
source: z6.string().min(1),
|
|
13501
13807
|
expectedSha256: HexSha
|
|
13502
13808
|
}).strict(),
|
|
13503
|
-
|
|
13504
|
-
action:
|
|
13505
|
-
project:
|
|
13506
|
-
assetId:
|
|
13507
|
-
styleId:
|
|
13809
|
+
z6.object({
|
|
13810
|
+
action: z6.literal("clear-source"),
|
|
13811
|
+
project: z6.string().min(1).optional(),
|
|
13812
|
+
assetId: z6.string().min(1),
|
|
13813
|
+
styleId: z6.string().min(1),
|
|
13508
13814
|
expectedSha256: HexSha
|
|
13509
13815
|
}).strict(),
|
|
13510
|
-
|
|
13511
|
-
action:
|
|
13512
|
-
project:
|
|
13513
|
-
styleId:
|
|
13816
|
+
z6.object({
|
|
13817
|
+
action: z6.literal("patch-style"),
|
|
13818
|
+
project: z6.string().min(1).optional(),
|
|
13819
|
+
styleId: z6.string().min(1),
|
|
13514
13820
|
expectedSha256: HexSha,
|
|
13515
|
-
patch:
|
|
13821
|
+
patch: z6.object({
|
|
13516
13822
|
/** Candidates per generation, written to the provider's own option. */
|
|
13517
|
-
candidates:
|
|
13823
|
+
candidates: z6.number().int().min(1).max(64).optional(),
|
|
13518
13824
|
/** Empty clears the style's own value (inherit, or the default). */
|
|
13519
|
-
promptPrefix:
|
|
13520
|
-
promptSuffix:
|
|
13825
|
+
promptPrefix: z6.string().optional(),
|
|
13826
|
+
promptSuffix: z6.string().optional(),
|
|
13521
13827
|
/** `#rrggbb` values; null or empty clears the style's own palette. */
|
|
13522
|
-
palette:
|
|
13828
|
+
palette: z6.array(z6.string().regex(/^#?[0-9a-f]{6}$/i, "expected a six-digit hex colour")).max(256).nullable().optional(),
|
|
13523
13829
|
/** Snap downloaded art to the palette; false clears the style's own value. */
|
|
13524
|
-
enforcePalette:
|
|
13830
|
+
enforcePalette: z6.boolean().optional(),
|
|
13525
13831
|
/** Provider view name (PixelLab: low top-down, high top-down, side); empty clears. */
|
|
13526
|
-
view:
|
|
13832
|
+
view: z6.string().max(64).nullable().optional(),
|
|
13527
13833
|
/** pixflux only; null clears the style's own value. */
|
|
13528
|
-
noBackground:
|
|
13834
|
+
noBackground: z6.boolean().nullable().optional()
|
|
13529
13835
|
}).strict().refine((patch) => Object.keys(patch).length > 0, { message: "nothing to change" })
|
|
13530
13836
|
}).strict()
|
|
13531
13837
|
]);
|
|
@@ -13808,35 +14114,35 @@ async function detachHandEdit(loaded, spec, opts = {}) {
|
|
|
13808
14114
|
});
|
|
13809
14115
|
return { manifestSha256: result.sha256, changed: result.changed };
|
|
13810
14116
|
}
|
|
13811
|
-
var CompanionOutputSchema =
|
|
14117
|
+
var CompanionOutputSchema = z7.object({
|
|
13812
14118
|
/** Output role for a set member; null for a single image. */
|
|
13813
|
-
role:
|
|
14119
|
+
role: z7.string().nullable(),
|
|
13814
14120
|
/** sha256 of the generated file this member started from; null when it started from untracked art. */
|
|
13815
|
-
basedOn:
|
|
14121
|
+
basedOn: z7.string().regex(/^[0-9a-f]{64}$/).nullable(),
|
|
13816
14122
|
/** sha256 of the member as saved, so a later change by another tool is visible. */
|
|
13817
|
-
sha256:
|
|
14123
|
+
sha256: z7.string().regex(/^[0-9a-f]{64}$/)
|
|
13818
14124
|
}).strict();
|
|
13819
|
-
var CompanionV2Schema =
|
|
13820
|
-
version:
|
|
14125
|
+
var CompanionV2Schema = z7.object({
|
|
14126
|
+
version: z7.literal(2),
|
|
13821
14127
|
/** Editor identity the bridge reported, e.g. `pixelorama@v1.2.2-stable`. */
|
|
13822
|
-
editor:
|
|
13823
|
-
protocol:
|
|
13824
|
-
savedAt:
|
|
14128
|
+
editor: z7.string().min(1),
|
|
14129
|
+
protocol: z7.number().int().positive(),
|
|
14130
|
+
savedAt: z7.string().datetime(),
|
|
13825
14131
|
/** Basename of the layered project file beside the edit, when one was kept. */
|
|
13826
|
-
project:
|
|
14132
|
+
project: z7.string().min(1).nullable(),
|
|
13827
14133
|
/** One entry per file, in output order. */
|
|
13828
|
-
outputs:
|
|
14134
|
+
outputs: z7.array(CompanionOutputSchema).min(1)
|
|
13829
14135
|
}).strict();
|
|
13830
|
-
var CompanionV1Schema =
|
|
13831
|
-
version:
|
|
13832
|
-
basedOn:
|
|
13833
|
-
sha256:
|
|
13834
|
-
editor:
|
|
13835
|
-
protocol:
|
|
13836
|
-
savedAt:
|
|
13837
|
-
project:
|
|
14136
|
+
var CompanionV1Schema = z7.object({
|
|
14137
|
+
version: z7.literal(1),
|
|
14138
|
+
basedOn: z7.string().regex(/^[0-9a-f]{64}$/).nullable(),
|
|
14139
|
+
sha256: z7.string().regex(/^[0-9a-f]{64}$/),
|
|
14140
|
+
editor: z7.string().min(1),
|
|
14141
|
+
protocol: z7.number().int().positive(),
|
|
14142
|
+
savedAt: z7.string().datetime(),
|
|
14143
|
+
project: z7.string().min(1).nullable()
|
|
13838
14144
|
}).strict();
|
|
13839
|
-
var HandEditCompanionSchema =
|
|
14145
|
+
var HandEditCompanionSchema = z7.union([CompanionV2Schema, CompanionV1Schema]).transform(
|
|
13840
14146
|
(value) => value.version === 2 ? value : {
|
|
13841
14147
|
version: 2,
|
|
13842
14148
|
editor: value.editor,
|
|
@@ -13995,41 +14301,41 @@ import path28 from "path";
|
|
|
13995
14301
|
|
|
13996
14302
|
// src/gallery/edit.ts
|
|
13997
14303
|
import path26 from "path";
|
|
13998
|
-
import { z as
|
|
13999
|
-
var Base64 =
|
|
14000
|
-
var HandEditRequestSchema =
|
|
14001
|
-
|
|
14002
|
-
action:
|
|
14003
|
-
project:
|
|
14004
|
-
assetId:
|
|
14005
|
-
styleId:
|
|
14006
|
-
expectedSha256:
|
|
14304
|
+
import { z as z8 } from "zod";
|
|
14305
|
+
var Base64 = z8.string().regex(/^[A-Za-z0-9+/]*={0,2}$/).max(Math.ceil(MAX_HAND_EDIT_BYTES / 3) * 4);
|
|
14306
|
+
var HandEditRequestSchema = z8.discriminatedUnion("action", [
|
|
14307
|
+
z8.object({
|
|
14308
|
+
action: z8.literal("start-edit"),
|
|
14309
|
+
project: z8.string().min(1).optional(),
|
|
14310
|
+
assetId: z8.string().min(1),
|
|
14311
|
+
styleId: z8.string().min(1),
|
|
14312
|
+
expectedSha256: z8.string().regex(/^[0-9a-f]{64}$/),
|
|
14007
14313
|
/** Also launch the author's editor on the file. */
|
|
14008
|
-
open:
|
|
14314
|
+
open: z8.boolean().optional()
|
|
14009
14315
|
}).strict(),
|
|
14010
|
-
|
|
14011
|
-
action:
|
|
14012
|
-
project:
|
|
14013
|
-
assetId:
|
|
14014
|
-
styleId:
|
|
14015
|
-
expectedSha256:
|
|
14316
|
+
z8.object({
|
|
14317
|
+
action: z8.literal("detach-edit"),
|
|
14318
|
+
project: z8.string().min(1).optional(),
|
|
14319
|
+
assetId: z8.string().min(1),
|
|
14320
|
+
styleId: z8.string().min(1),
|
|
14321
|
+
expectedSha256: z8.string().regex(/^[0-9a-f]{64}$/)
|
|
14016
14322
|
}).strict(),
|
|
14017
14323
|
/** From the in-browser editor: the page holds the bytes, the server validates and writes. */
|
|
14018
|
-
|
|
14019
|
-
action:
|
|
14020
|
-
project:
|
|
14021
|
-
assetId:
|
|
14022
|
-
styleId:
|
|
14023
|
-
expectedSha256:
|
|
14324
|
+
z8.object({
|
|
14325
|
+
action: z8.literal("save-edit"),
|
|
14326
|
+
project: z8.string().min(1).optional(),
|
|
14327
|
+
assetId: z8.string().min(1),
|
|
14328
|
+
styleId: z8.string().min(1),
|
|
14329
|
+
expectedSha256: z8.string().regex(/^[0-9a-f]{64}$/),
|
|
14024
14330
|
/** The flattened image; for a frame set, `frames` instead. */
|
|
14025
14331
|
png: Base64.min(1).optional(),
|
|
14026
14332
|
/** Every frame of a set, tagged with the role it was opened under (null for one added in the editor). */
|
|
14027
|
-
frames:
|
|
14333
|
+
frames: z8.array(z8.object({ role: z8.string().min(1).nullable(), png: Base64.min(1) }).strict()).min(1).max(256).optional(),
|
|
14028
14334
|
/** The editor's layered project file, kept beside the edit. */
|
|
14029
14335
|
pxo: Base64.optional(),
|
|
14030
14336
|
/** Editor identity from the bridge's ready message. */
|
|
14031
|
-
editor:
|
|
14032
|
-
protocol:
|
|
14337
|
+
editor: z8.string().min(1).max(200),
|
|
14338
|
+
protocol: z8.number().int().positive()
|
|
14033
14339
|
}).strict()
|
|
14034
14340
|
]);
|
|
14035
14341
|
function createGalleryEditHandler(opts) {
|
|
@@ -15213,7 +15519,7 @@ async function serveGallery(opts) {
|
|
|
15213
15519
|
|
|
15214
15520
|
// src/gallery/generate.ts
|
|
15215
15521
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
15216
|
-
import { z as
|
|
15522
|
+
import { z as z9 } from "zod";
|
|
15217
15523
|
|
|
15218
15524
|
// src/pipeline/poll.ts
|
|
15219
15525
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -15494,6 +15800,9 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
|
|
|
15494
15800
|
...spec.revision.lastFrameSha256 ? { lastFrameSha256: spec.revision.lastFrameSha256 } : {},
|
|
15495
15801
|
...spec.revision.direction ? { direction: spec.revision.direction } : {},
|
|
15496
15802
|
...spec.revision.enhancePrompt == null ? {} : { enhancePrompt: spec.revision.enhancePrompt },
|
|
15803
|
+
...spec.revision.keypointsSha256 ? { keypointsSha256: spec.revision.keypointsSha256 } : {},
|
|
15804
|
+
...spec.revision.skeletonTemplate ? { skeletonTemplate: spec.revision.skeletonTemplate } : {},
|
|
15805
|
+
...spec.revision.description ? { description: spec.revision.description } : {},
|
|
15497
15806
|
...spec.revision.engine ? { engine: spec.revision.engine } : {}
|
|
15498
15807
|
} : null,
|
|
15499
15808
|
outfit: spec.character?.kind === "outfit" && outfitParentEntry ? {
|
|
@@ -16310,26 +16619,26 @@ async function runPicker(provider, lock, lockPath, opts = {}) {
|
|
|
16310
16619
|
}
|
|
16311
16620
|
|
|
16312
16621
|
// src/gallery/generate.ts
|
|
16313
|
-
var GenerateRequestSchema =
|
|
16314
|
-
project:
|
|
16315
|
-
keys:
|
|
16622
|
+
var GenerateRequestSchema = z9.object({
|
|
16623
|
+
project: z9.string().min(1).optional(),
|
|
16624
|
+
keys: z9.array(z9.string().min(1)).min(1).max(500),
|
|
16316
16625
|
/**
|
|
16317
16626
|
* Regenerate work that is up to date, as `gen --force` does, and let the
|
|
16318
16627
|
* fetch replace a locally modified or untracked file. With `restore`, put
|
|
16319
16628
|
* the recorded bytes back over a modified file.
|
|
16320
16629
|
*/
|
|
16321
|
-
force:
|
|
16630
|
+
force: z9.boolean().optional(),
|
|
16322
16631
|
/** Advance in-flight, review, or selected work without submitting anything. */
|
|
16323
|
-
resume:
|
|
16632
|
+
resume: z9.boolean().optional(),
|
|
16324
16633
|
/** Re-download downloaded outputs and replace files whose object changed upstream. */
|
|
16325
|
-
refresh:
|
|
16634
|
+
refresh: z9.boolean().optional(),
|
|
16326
16635
|
/** Put recorded outputs back on disk from the cache or the provider, without generating. */
|
|
16327
|
-
restore:
|
|
16636
|
+
restore: z9.boolean().optional(),
|
|
16328
16637
|
/**
|
|
16329
16638
|
* Bring a replaced generation back: 1-based position in the record's
|
|
16330
16639
|
* history (newest first) or an output hash prefix. One key at a time.
|
|
16331
16640
|
*/
|
|
16332
|
-
revert:
|
|
16641
|
+
revert: z9.string().min(1).max(64).optional()
|
|
16333
16642
|
}).strict().refine((request) => [request.resume, request.refresh, request.restore, request.revert !== void 0].filter(Boolean).length <= 1, {
|
|
16334
16643
|
message: "resume, refresh, restore, and revert are exclusive"
|
|
16335
16644
|
}).refine((request) => request.revert === void 0 || request.keys.length === 1, { message: "revert takes one key" });
|
|
@@ -19215,11 +19524,11 @@ import { readFile as readFile28 } from "fs/promises";
|
|
|
19215
19524
|
import path41 from "path";
|
|
19216
19525
|
import { existsSync as existsSync30 } from "fs";
|
|
19217
19526
|
import { readFile as readFile27 } from "fs/promises";
|
|
19218
|
-
import { z as
|
|
19527
|
+
import { z as z10 } from "zod";
|
|
19219
19528
|
var SHA256_RE = /^[0-9a-f]{64}$/;
|
|
19220
19529
|
var HEX_RE = /^#[0-9a-f]{6}$/;
|
|
19221
19530
|
var MAX_REDMEAN_DISTANCE = 765;
|
|
19222
|
-
var QualityPathSchema =
|
|
19531
|
+
var QualityPathSchema = z10.string().min(1).refine(
|
|
19223
19532
|
(value) => !path41.posix.isAbsolute(value) && !value.includes("\\"),
|
|
19224
19533
|
"expected a portable relative path"
|
|
19225
19534
|
);
|
|
@@ -19233,53 +19542,53 @@ var DEFAULT_QUALITY_TOLERANCES = {
|
|
|
19233
19542
|
maxEdgeContrastDrop: 0.03,
|
|
19234
19543
|
maxIsolatedPixelIncrease: 5e-3
|
|
19235
19544
|
};
|
|
19236
|
-
var QualityToleranceSchema =
|
|
19237
|
-
requireExactHash:
|
|
19238
|
-
maxColorCountIncrease:
|
|
19239
|
-
maxNewColors:
|
|
19240
|
-
maxTransparencyDelta:
|
|
19241
|
-
maxPartialAlphaIncrease:
|
|
19242
|
-
maxEdgeDensityDelta:
|
|
19243
|
-
maxEdgeContrastDrop:
|
|
19244
|
-
maxIsolatedPixelIncrease:
|
|
19545
|
+
var QualityToleranceSchema = z10.object({
|
|
19546
|
+
requireExactHash: z10.boolean(),
|
|
19547
|
+
maxColorCountIncrease: z10.number().int().min(0),
|
|
19548
|
+
maxNewColors: z10.number().int().min(0),
|
|
19549
|
+
maxTransparencyDelta: z10.number().min(0).max(1),
|
|
19550
|
+
maxPartialAlphaIncrease: z10.number().min(0).max(1),
|
|
19551
|
+
maxEdgeDensityDelta: z10.number().min(0).max(1),
|
|
19552
|
+
maxEdgeContrastDrop: z10.number().min(0).max(1),
|
|
19553
|
+
maxIsolatedPixelIncrease: z10.number().min(0).max(1)
|
|
19245
19554
|
}).strict();
|
|
19246
|
-
var ImageQualityMetricsSchema =
|
|
19247
|
-
sha256:
|
|
19248
|
-
width:
|
|
19249
|
-
height:
|
|
19250
|
-
colorCount:
|
|
19251
|
-
colors:
|
|
19252
|
-
transparency:
|
|
19253
|
-
partialAlpha:
|
|
19254
|
-
edgeDensity:
|
|
19255
|
-
meanEdgeContrast:
|
|
19256
|
-
isolatedPixelRatio:
|
|
19555
|
+
var ImageQualityMetricsSchema = z10.object({
|
|
19556
|
+
sha256: z10.string().regex(SHA256_RE),
|
|
19557
|
+
width: z10.number().int().min(1),
|
|
19558
|
+
height: z10.number().int().min(1),
|
|
19559
|
+
colorCount: z10.number().int().min(0),
|
|
19560
|
+
colors: z10.array(z10.string().regex(HEX_RE)),
|
|
19561
|
+
transparency: z10.number().min(0).max(1),
|
|
19562
|
+
partialAlpha: z10.number().min(0).max(1),
|
|
19563
|
+
edgeDensity: z10.number().min(0).max(1),
|
|
19564
|
+
meanEdgeContrast: z10.number().min(0).max(1),
|
|
19565
|
+
isolatedPixelRatio: z10.number().min(0).max(1)
|
|
19257
19566
|
}).strict();
|
|
19258
|
-
var QualityBaselineCaseSchema =
|
|
19259
|
-
id:
|
|
19567
|
+
var QualityBaselineCaseSchema = z10.object({
|
|
19568
|
+
id: z10.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),
|
|
19260
19569
|
file: QualityPathSchema,
|
|
19261
|
-
record:
|
|
19570
|
+
record: z10.object({
|
|
19262
19571
|
path: QualityPathSchema,
|
|
19263
|
-
sha256:
|
|
19572
|
+
sha256: z10.string().regex(SHA256_RE)
|
|
19264
19573
|
}).strict().optional(),
|
|
19265
19574
|
expected: ImageQualityMetricsSchema,
|
|
19266
19575
|
tolerances: QualityToleranceSchema
|
|
19267
19576
|
}).strict();
|
|
19268
|
-
var QualityBaselineSchema =
|
|
19269
|
-
$schema:
|
|
19270
|
-
format:
|
|
19271
|
-
schemaVersion:
|
|
19272
|
-
cases:
|
|
19577
|
+
var QualityBaselineSchema = z10.object({
|
|
19578
|
+
$schema: z10.string().url().optional(),
|
|
19579
|
+
format: z10.literal("pixelkiln-quality-baseline"),
|
|
19580
|
+
schemaVersion: z10.literal(1),
|
|
19581
|
+
cases: z10.array(QualityBaselineCaseSchema).min(1)
|
|
19273
19582
|
}).strict().superRefine((baseline, context) => {
|
|
19274
19583
|
const ids = baseline.cases.map((entry) => entry.id);
|
|
19275
19584
|
if (new Set(ids).size !== ids.length) {
|
|
19276
|
-
context.addIssue({ code:
|
|
19585
|
+
context.addIssue({ code: z10.ZodIssueCode.custom, path: ["cases"], message: "duplicate case id" });
|
|
19277
19586
|
}
|
|
19278
19587
|
});
|
|
19279
|
-
var QualityInputSchema =
|
|
19280
|
-
id:
|
|
19281
|
-
path:
|
|
19282
|
-
record:
|
|
19588
|
+
var QualityInputSchema = z10.object({
|
|
19589
|
+
id: z10.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),
|
|
19590
|
+
path: z10.string().min(1),
|
|
19591
|
+
record: z10.string().min(1).optional(),
|
|
19283
19592
|
tolerances: QualityToleranceSchema.partial().optional()
|
|
19284
19593
|
}).strict();
|
|
19285
19594
|
function message4(error) {
|
|
@@ -19381,7 +19690,7 @@ async function measureImageQuality(file) {
|
|
|
19381
19690
|
}
|
|
19382
19691
|
}
|
|
19383
19692
|
function resolveQualityInputs(raw, inputsFilePath) {
|
|
19384
|
-
const parsed =
|
|
19693
|
+
const parsed = z10.array(QualityInputSchema).min(1).safeParse(raw);
|
|
19385
19694
|
if (!parsed.success) {
|
|
19386
19695
|
throw new Error(
|
|
19387
19696
|
"--inputs must be a non-empty JSON array of quality cases:\n" + parsed.error.issues.map((issue) => ` ${issue.path.join(".") || "$"}: ${issue.message}`).join("\n")
|
|
@@ -19656,47 +19965,47 @@ import path43 from "path";
|
|
|
19656
19965
|
import { existsSync as existsSync31 } from "fs";
|
|
19657
19966
|
import { readdir as readdir3, readFile as readFile29 } from "fs/promises";
|
|
19658
19967
|
import { fileURLToPath } from "url";
|
|
19659
|
-
import { z as
|
|
19968
|
+
import { z as z11 } from "zod";
|
|
19660
19969
|
var SHA256_RE2 = /^[0-9a-f]{64}$/;
|
|
19661
19970
|
var RECIPE_ID_RE = /^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/;
|
|
19662
19971
|
var VERSION_RE = /^\d+\.\d+\.\d+$/;
|
|
19663
19972
|
var RECIPE_FILE = "pixelkiln.recipe.json";
|
|
19664
19973
|
var RECIPE_DIR_TOKEN = "{{recipeDir}}";
|
|
19665
|
-
var PortablePathSchema =
|
|
19974
|
+
var PortablePathSchema = z11.string().min(1).refine((value) => {
|
|
19666
19975
|
if (value.includes("\\") || path43.posix.isAbsolute(value)) return false;
|
|
19667
19976
|
const parts = value.split("/");
|
|
19668
19977
|
return !parts.includes("") && !parts.includes(".") && !parts.includes("..");
|
|
19669
19978
|
}, "expected a portable relative path without '.', '..', or backslashes");
|
|
19670
|
-
var RecipeBindingSchema =
|
|
19671
|
-
nodeId:
|
|
19672
|
-
input:
|
|
19979
|
+
var RecipeBindingSchema = z11.object({
|
|
19980
|
+
nodeId: z11.string().min(1),
|
|
19981
|
+
input: z11.string().min(1)
|
|
19673
19982
|
}).strict();
|
|
19674
|
-
var RecipeSchema =
|
|
19675
|
-
$schema:
|
|
19676
|
-
format:
|
|
19677
|
-
schemaVersion:
|
|
19678
|
-
id:
|
|
19679
|
-
version:
|
|
19680
|
-
provider:
|
|
19681
|
-
summary:
|
|
19682
|
-
files:
|
|
19983
|
+
var RecipeSchema = z11.object({
|
|
19984
|
+
$schema: z11.string().url().optional(),
|
|
19985
|
+
format: z11.literal("pixelkiln-recipe"),
|
|
19986
|
+
schemaVersion: z11.literal(1),
|
|
19987
|
+
id: z11.string().regex(RECIPE_ID_RE, "expected provider/name"),
|
|
19988
|
+
version: z11.string().regex(VERSION_RE, "expected x.y.z"),
|
|
19989
|
+
provider: z11.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
19990
|
+
summary: z11.string().min(1).max(240),
|
|
19991
|
+
files: z11.array(z11.object({
|
|
19683
19992
|
path: PortablePathSchema,
|
|
19684
|
-
role:
|
|
19685
|
-
sha256:
|
|
19993
|
+
role: z11.enum(["workflow", "reference"]),
|
|
19994
|
+
sha256: z11.string().regex(SHA256_RE2)
|
|
19686
19995
|
}).strict()).default([]),
|
|
19687
|
-
models:
|
|
19996
|
+
models: z11.array(z11.object({
|
|
19688
19997
|
path: PortablePathSchema,
|
|
19689
|
-
sha256:
|
|
19690
|
-
source:
|
|
19691
|
-
license:
|
|
19998
|
+
sha256: z11.string().regex(SHA256_RE2),
|
|
19999
|
+
source: z11.string().url(),
|
|
20000
|
+
license: z11.string().min(1)
|
|
19692
20001
|
}).strict()).default([]),
|
|
19693
|
-
styleId:
|
|
20002
|
+
styleId: z11.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
19694
20003
|
style: StyleSchema,
|
|
19695
|
-
workflow:
|
|
20004
|
+
workflow: z11.object({
|
|
19696
20005
|
path: PortablePathSchema,
|
|
19697
|
-
outputNodeId:
|
|
19698
|
-
numImages:
|
|
19699
|
-
bindings:
|
|
20006
|
+
outputNodeId: z11.string().min(1),
|
|
20007
|
+
numImages: z11.number().int().min(1).max(16),
|
|
20008
|
+
bindings: z11.object({
|
|
19700
20009
|
prompt: RecipeBindingSchema,
|
|
19701
20010
|
width: RecipeBindingSchema.optional(),
|
|
19702
20011
|
height: RecipeBindingSchema.optional(),
|
|
@@ -19707,67 +20016,67 @@ var RecipeSchema = z10.object({
|
|
|
19707
20016
|
strength: RecipeBindingSchema.optional()
|
|
19708
20017
|
}).strict()
|
|
19709
20018
|
}).strict().optional(),
|
|
19710
|
-
quality:
|
|
19711
|
-
stage:
|
|
19712
|
-
workingCanvas:
|
|
19713
|
-
width:
|
|
19714
|
-
height:
|
|
20019
|
+
quality: z11.object({
|
|
20020
|
+
stage: z11.enum(["composition-source", "production-candidate"]),
|
|
20021
|
+
workingCanvas: z11.object({
|
|
20022
|
+
width: z11.number().int().min(16),
|
|
20023
|
+
height: z11.number().int().min(16)
|
|
19715
20024
|
}).strict(),
|
|
19716
|
-
recommendedNativeSize:
|
|
19717
|
-
min:
|
|
19718
|
-
max:
|
|
20025
|
+
recommendedNativeSize: z11.object({
|
|
20026
|
+
min: z11.number().int().min(1),
|
|
20027
|
+
max: z11.number().int().min(1)
|
|
19719
20028
|
}).strict(),
|
|
19720
|
-
paletteColors:
|
|
19721
|
-
min:
|
|
19722
|
-
max:
|
|
20029
|
+
paletteColors: z11.object({
|
|
20030
|
+
min: z11.number().int().min(1),
|
|
20031
|
+
max: z11.number().int().min(1)
|
|
19723
20032
|
}).strict(),
|
|
19724
|
-
background:
|
|
19725
|
-
checks:
|
|
20033
|
+
background: z11.enum(["opaque", "transparent", "full-bleed"]),
|
|
20034
|
+
checks: z11.array(z11.enum([
|
|
19726
20035
|
"prompt-coverage",
|
|
19727
20036
|
"native-grid",
|
|
19728
20037
|
"final-palette",
|
|
19729
20038
|
"alpha-edge",
|
|
19730
20039
|
"human-1x"
|
|
19731
20040
|
])).min(1),
|
|
19732
|
-
notes:
|
|
20041
|
+
notes: z11.array(z11.string().min(1)).default([])
|
|
19733
20042
|
}).strict(),
|
|
19734
|
-
integrity:
|
|
19735
|
-
algorithm:
|
|
19736
|
-
digest:
|
|
20043
|
+
integrity: z11.object({
|
|
20044
|
+
algorithm: z11.literal("sha256"),
|
|
20045
|
+
digest: z11.string().regex(SHA256_RE2)
|
|
19737
20046
|
}).strict()
|
|
19738
20047
|
}).strict().superRefine((recipe, context) => {
|
|
19739
20048
|
if (recipe.style.provider && recipe.style.provider !== recipe.provider) {
|
|
19740
20049
|
context.addIssue({
|
|
19741
|
-
code:
|
|
20050
|
+
code: z11.ZodIssueCode.custom,
|
|
19742
20051
|
path: ["style", "provider"],
|
|
19743
20052
|
message: "must match the recipe provider"
|
|
19744
20053
|
});
|
|
19745
20054
|
}
|
|
19746
20055
|
const filePaths = recipe.files.map((file) => file.path);
|
|
19747
20056
|
if (new Set(filePaths).size !== filePaths.length) {
|
|
19748
|
-
context.addIssue({ code:
|
|
20057
|
+
context.addIssue({ code: z11.ZodIssueCode.custom, path: ["files"], message: "duplicate file path" });
|
|
19749
20058
|
}
|
|
19750
20059
|
const modelPaths = recipe.models.map((model) => model.path);
|
|
19751
20060
|
if (new Set(modelPaths).size !== modelPaths.length) {
|
|
19752
|
-
context.addIssue({ code:
|
|
20061
|
+
context.addIssue({ code: z11.ZodIssueCode.custom, path: ["models"], message: "duplicate model path" });
|
|
19753
20062
|
}
|
|
19754
20063
|
if (filePaths.includes(RECIPE_FILE)) {
|
|
19755
20064
|
context.addIssue({
|
|
19756
|
-
code:
|
|
20065
|
+
code: z11.ZodIssueCode.custom,
|
|
19757
20066
|
path: ["files"],
|
|
19758
20067
|
message: `${RECIPE_FILE} cannot hash itself`
|
|
19759
20068
|
});
|
|
19760
20069
|
}
|
|
19761
20070
|
if (recipe.quality.recommendedNativeSize.min > recipe.quality.recommendedNativeSize.max) {
|
|
19762
20071
|
context.addIssue({
|
|
19763
|
-
code:
|
|
20072
|
+
code: z11.ZodIssueCode.custom,
|
|
19764
20073
|
path: ["quality", "recommendedNativeSize"],
|
|
19765
20074
|
message: "min cannot exceed max"
|
|
19766
20075
|
});
|
|
19767
20076
|
}
|
|
19768
20077
|
if (recipe.quality.paletteColors.min > recipe.quality.paletteColors.max) {
|
|
19769
20078
|
context.addIssue({
|
|
19770
|
-
code:
|
|
20079
|
+
code: z11.ZodIssueCode.custom,
|
|
19771
20080
|
path: ["quality", "paletteColors"],
|
|
19772
20081
|
message: "min cannot exceed max"
|
|
19773
20082
|
});
|
|
@@ -19776,7 +20085,7 @@ var RecipeSchema = z10.object({
|
|
|
19776
20085
|
(file) => file.path === recipe.workflow.path && file.role === "workflow"
|
|
19777
20086
|
)) {
|
|
19778
20087
|
context.addIssue({
|
|
19779
|
-
code:
|
|
20088
|
+
code: z11.ZodIssueCode.custom,
|
|
19780
20089
|
path: ["workflow", "path"],
|
|
19781
20090
|
message: "must name a file whose role is workflow"
|
|
19782
20091
|
});
|
|
@@ -19784,7 +20093,7 @@ var RecipeSchema = z10.object({
|
|
|
19784
20093
|
if (recipe.provider === "comfyui") {
|
|
19785
20094
|
if (!recipe.workflow) {
|
|
19786
20095
|
context.addIssue({
|
|
19787
|
-
code:
|
|
20096
|
+
code: z11.ZodIssueCode.custom,
|
|
19788
20097
|
path: ["workflow"],
|
|
19789
20098
|
message: "ComfyUI recipes require workflow metadata"
|
|
19790
20099
|
});
|
|
@@ -19793,7 +20102,7 @@ var RecipeSchema = z10.object({
|
|
|
19793
20102
|
const options = recipe.style.providerOptions.comfyui;
|
|
19794
20103
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
19795
20104
|
context.addIssue({
|
|
19796
|
-
code:
|
|
20105
|
+
code: z11.ZodIssueCode.custom,
|
|
19797
20106
|
path: ["style", "providerOptions", "comfyui"],
|
|
19798
20107
|
message: "ComfyUI recipes require ComfyUI provider options"
|
|
19799
20108
|
});
|
|
@@ -19807,7 +20116,7 @@ var RecipeSchema = z10.object({
|
|
|
19807
20116
|
};
|
|
19808
20117
|
if (JSON.stringify(canonical3(options)) !== JSON.stringify(canonical3(expected))) {
|
|
19809
20118
|
context.addIssue({
|
|
19810
|
-
code:
|
|
20119
|
+
code: z11.ZodIssueCode.custom,
|
|
19811
20120
|
path: ["style", "providerOptions", "comfyui"],
|
|
19812
20121
|
message: "must match workflow metadata and use {{recipeDir}} for workflowFile"
|
|
19813
20122
|
});
|
|
@@ -20226,6 +20535,30 @@ async function runRefine(args) {
|
|
|
20226
20535
|
if (result.failed) process.exitCode = 1;
|
|
20227
20536
|
}
|
|
20228
20537
|
|
|
20538
|
+
// src/cli/commands/skeleton.ts
|
|
20539
|
+
import path46 from "path";
|
|
20540
|
+
import { readFile as readFile30, writeFile as writeFile15 } from "fs/promises";
|
|
20541
|
+
async function runEstimateSkeleton(args) {
|
|
20542
|
+
const image = args.target;
|
|
20543
|
+
if (!image) throw new UsageError("estimate-skeleton needs an image path: pixelkiln estimate-skeleton <image> [--out keypoints.json]");
|
|
20544
|
+
loadEnvFiles(path46.dirname(path46.resolve(args.manifest)));
|
|
20545
|
+
loadEnvFiles(process.cwd());
|
|
20546
|
+
const bytes = await readFile30(path46.resolve(image));
|
|
20547
|
+
const metadata = imageMetadata(bytes);
|
|
20548
|
+
if (!metadata) throw new UsageError(`${image} is not a readable PNG or JPEG`);
|
|
20549
|
+
const client2 = clientFromEnv();
|
|
20550
|
+
const res = await client2.estimateSkeleton({
|
|
20551
|
+
image: { base64: bytes.toString("base64"), format: metadata.format }
|
|
20552
|
+
});
|
|
20553
|
+
const json = JSON.stringify(res.keypoints, null, 2);
|
|
20554
|
+
if (args.out) {
|
|
20555
|
+
await writeFile15(path46.resolve(args.out), json + "\n");
|
|
20556
|
+
log(` wrote ${res.keypoints.length} keypoints to ${args.out}`);
|
|
20557
|
+
} else {
|
|
20558
|
+
log(json);
|
|
20559
|
+
}
|
|
20560
|
+
}
|
|
20561
|
+
|
|
20229
20562
|
// src/cli/commands/tools.ts
|
|
20230
20563
|
async function runTools(args) {
|
|
20231
20564
|
const mb = (bytes) => bytes < 1e6 ? `${(bytes / 1e3).toFixed(0)} kB` : `${(bytes / 1e6).toFixed(1)} MB`;
|
|
@@ -20268,15 +20601,15 @@ async function runTools(args) {
|
|
|
20268
20601
|
}
|
|
20269
20602
|
|
|
20270
20603
|
// src/cli/commands/workspace.ts
|
|
20271
|
-
import
|
|
20604
|
+
import path47 from "path";
|
|
20272
20605
|
import { existsSync as existsSync32 } from "fs";
|
|
20273
20606
|
async function runWorkspace(args) {
|
|
20274
|
-
const workspacePath =
|
|
20275
|
-
const dir =
|
|
20607
|
+
const workspacePath = path47.resolve(args.workspace ?? "pixelkiln.workspace.json");
|
|
20608
|
+
const dir = path47.dirname(workspacePath);
|
|
20276
20609
|
if (args.subcommand === "add") {
|
|
20277
|
-
const manifestPath =
|
|
20610
|
+
const manifestPath = path47.resolve(args.target);
|
|
20278
20611
|
const loadedTarget = await loadManifest(manifestPath);
|
|
20279
|
-
const lockPath = args.explicitLock ?
|
|
20612
|
+
const lockPath = args.explicitLock ? path47.resolve(args.explicitLock) : path47.join(path47.dirname(manifestPath), "pixelkiln.lock.json");
|
|
20280
20613
|
const ws = await loadWorkspace(workspacePath);
|
|
20281
20614
|
const id = args.name ?? loadedTarget.manifest.name;
|
|
20282
20615
|
if (ws.projects.some((p) => p.id === id)) {
|
|
@@ -20296,7 +20629,7 @@ async function runWorkspace(args) {
|
|
|
20296
20629
|
...args.account ? { account: args.account } : {}
|
|
20297
20630
|
};
|
|
20298
20631
|
await saveWorkspace(workspacePath, { version: 1, projects: [...ws.projects, project] });
|
|
20299
|
-
log(` registered "${id}" in ${
|
|
20632
|
+
log(` registered "${id}" in ${path47.relative(process.cwd(), workspacePath)}`);
|
|
20300
20633
|
log(` manifest: ${project.manifest}`);
|
|
20301
20634
|
log(` lock: ${project.lock}`);
|
|
20302
20635
|
if (!existsSync32(lockPath)) {
|
|
@@ -20308,7 +20641,7 @@ async function runWorkspace(args) {
|
|
|
20308
20641
|
}
|
|
20309
20642
|
if (args.subcommand === "remove") {
|
|
20310
20643
|
const ws = await loadWorkspace(workspacePath);
|
|
20311
|
-
const resolvedTarget =
|
|
20644
|
+
const resolvedTarget = path47.resolve(args.target);
|
|
20312
20645
|
const match = ws.projects.find(
|
|
20313
20646
|
(p) => p.id === args.target || resolveProject(dir, p).manifestPath === resolvedTarget
|
|
20314
20647
|
);
|
|
@@ -20319,7 +20652,7 @@ async function runWorkspace(args) {
|
|
|
20319
20652
|
version: 1,
|
|
20320
20653
|
projects: ws.projects.filter((p) => p !== match)
|
|
20321
20654
|
});
|
|
20322
|
-
log(` removed "${match.id}" from ${
|
|
20655
|
+
log(` removed "${match.id}" from ${path47.relative(process.cwd(), workspacePath)}`);
|
|
20323
20656
|
return;
|
|
20324
20657
|
}
|
|
20325
20658
|
if (args.subcommand === "list") {
|
|
@@ -20331,9 +20664,9 @@ async function runWorkspace(args) {
|
|
|
20331
20664
|
if (args.json) {
|
|
20332
20665
|
log(JSON.stringify({ version: 1, workspace: workspacePath, projects: ws.projects, diagnostics }, null, 2));
|
|
20333
20666
|
} else if (!ws.projects.length) {
|
|
20334
|
-
log(` no projects registered in ${
|
|
20667
|
+
log(` no projects registered in ${path47.relative(process.cwd(), workspacePath)}`);
|
|
20335
20668
|
} else {
|
|
20336
|
-
log(` ${ws.projects.length} project(s) in ${
|
|
20669
|
+
log(` ${ws.projects.length} project(s) in ${path47.relative(process.cwd(), workspacePath)}:`);
|
|
20337
20670
|
for (const p of ws.projects) {
|
|
20338
20671
|
log(` ${p.id.padEnd(24)} ${p.manifest.padEnd(40)} (${p.provider}${p.account ? `, ${p.account}` : ""})`);
|
|
20339
20672
|
}
|
|
@@ -20351,7 +20684,7 @@ async function runWorkspace(args) {
|
|
|
20351
20684
|
if (args.json) {
|
|
20352
20685
|
log(JSON.stringify({ ...report, workspace: workspacePath }, null, 2));
|
|
20353
20686
|
} else {
|
|
20354
|
-
log(` workspace: ${
|
|
20687
|
+
log(` workspace: ${path47.relative(process.cwd(), workspacePath)}`);
|
|
20355
20688
|
for (const p of report.projects) {
|
|
20356
20689
|
if (p.error) {
|
|
20357
20690
|
log(`
|
|
@@ -20406,7 +20739,7 @@ async function runVersion() {
|
|
|
20406
20739
|
for (const up of ["../package.json", "../../package.json"]) {
|
|
20407
20740
|
const url = new URL(up, import.meta.url);
|
|
20408
20741
|
if (!existsSync33(url)) continue;
|
|
20409
|
-
const pkg = JSON.parse(await
|
|
20742
|
+
const pkg = JSON.parse(await readFile31(url, "utf8"));
|
|
20410
20743
|
if (pkg.name === "pixelkiln") {
|
|
20411
20744
|
log(`${pkg.name} ${pkg.version}`);
|
|
20412
20745
|
return;
|
|
@@ -20450,6 +20783,7 @@ var RUNNERS = {
|
|
|
20450
20783
|
refine: runRefine,
|
|
20451
20784
|
recipe: runRecipe,
|
|
20452
20785
|
workspace: runWorkspace,
|
|
20786
|
+
"estimate-skeleton": runEstimateSkeleton,
|
|
20453
20787
|
unzoom: runUnzoom,
|
|
20454
20788
|
font: runFont
|
|
20455
20789
|
};
|