pixelkiln 0.44.0 → 0.46.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 +205 -35
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +204 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +674 -73
- package/dist/index.d.ts +674 -73
- package/dist/index.js +204 -34
- package/dist/index.js.map +1 -1
- package/docs/GENERATORS.md +1 -0
- package/docs/MANIFEST.md +42 -12
- package/package.json +1 -1
- package/schema/manifest.schema.json +56 -2
- package/schema/recipe.schema.json +24 -1
- package/skills/pixelkiln/references/pixellab.md +5 -2
package/dist/index.js
CHANGED
|
@@ -90,7 +90,7 @@ var MIRRORED_DIRECTION = {
|
|
|
90
90
|
west: "east",
|
|
91
91
|
"south-west": "south-east"
|
|
92
92
|
};
|
|
93
|
-
var CharacterModeSchema = z.enum(["standard", "v3", "pro"]);
|
|
93
|
+
var CharacterModeSchema = z.enum(["standard", "v3", "pro", "pro-flash"]);
|
|
94
94
|
var CHARACTER_PROPORTION_PRESETS = ["default", "chibi", "cartoon", "stylized", "realistic_male", "realistic_female", "heroic"];
|
|
95
95
|
var CharacterProportionsSchema = z.union([
|
|
96
96
|
z.enum(CHARACTER_PROPORTION_PRESETS),
|
|
@@ -286,14 +286,27 @@ var StyleObjectSchema = z.object({
|
|
|
286
286
|
/**
|
|
287
287
|
* `character` only. `standard` draws from a skeleton template for 1
|
|
288
288
|
* generation; `v3` is the highest quality at 2 to 9 by size; `pro` is a
|
|
289
|
-
* reference-based engine at 20 to 40 by size
|
|
290
|
-
*
|
|
289
|
+
* reference-based engine at 20 to 40 by size; `pro-flash` draws a
|
|
290
|
+
* south sprite with PixelLab's newest image model and rotates it with
|
|
291
|
+
* v3, 6 to 17 by size, or the rotations alone (1 at 64px) from a
|
|
292
|
+
* `reference`. States inherit the parent's engine; animations choose
|
|
293
|
+
* their own.
|
|
291
294
|
*/
|
|
292
295
|
mode: CharacterModeSchema.optional(),
|
|
293
|
-
/** `character` only. Rotations per base or state.
|
|
296
|
+
/** `character` only. Rotations per base or state. Every engine but `standard` draws 8. */
|
|
294
297
|
directions: z.union([z.literal(4), z.literal(8)]).optional(),
|
|
295
|
-
/** `character` only. Body template: `mannequin` (default)
|
|
298
|
+
/** `character` only. Body template: `mannequin` (default), a quadruped (`bear`, `cat`, `dog`, `horse`, `lion`), or `custom` for `pro-flash`. */
|
|
296
299
|
template: z.string().min(1).optional(),
|
|
300
|
+
/**
|
|
301
|
+
* `character` only, `pro-flash` bases with a style image: which traits
|
|
302
|
+
* the style image lends. Each defaults to true.
|
|
303
|
+
*/
|
|
304
|
+
styleTraits: z.object({
|
|
305
|
+
palette: z.boolean().optional(),
|
|
306
|
+
outline: z.boolean().optional(),
|
|
307
|
+
detail: z.boolean().optional(),
|
|
308
|
+
shading: z.boolean().optional()
|
|
309
|
+
}).strict().optional(),
|
|
297
310
|
/** `character` only, `standard` humanoid bases. A preset or multipliers; an asset may override it. */
|
|
298
311
|
proportions: CharacterProportionsSchema.optional(),
|
|
299
312
|
/**
|
|
@@ -306,6 +319,12 @@ var StyleObjectSchema = z.object({
|
|
|
306
319
|
isometric: z.boolean().optional(),
|
|
307
320
|
/** `character` only, `v3` bases: let PixelLab expand the prompt into a fuller one before drawing. */
|
|
308
321
|
enhancePrompt: z.boolean().optional(),
|
|
322
|
+
/**
|
|
323
|
+
* `character` only, `pro` bases: the asset id of a generated 8-direction
|
|
324
|
+
* character in this style whose look every base drawn from text or a
|
|
325
|
+
* concept follows. An asset may override it; the anchor itself ignores it.
|
|
326
|
+
*/
|
|
327
|
+
styleCharacter: z.string().min(1).optional(),
|
|
309
328
|
/** Fixed seed for reproducibility where the endpoint supports it. */
|
|
310
329
|
seed: z.number().int().optional(),
|
|
311
330
|
/**
|
|
@@ -478,6 +497,15 @@ var AssetSchema = z.object({
|
|
|
478
497
|
* still guides the result.
|
|
479
498
|
*/
|
|
480
499
|
reference: z.union([z.string().min(1), z.record(CharacterDirectionSchema, z.string().min(1))]).optional(),
|
|
500
|
+
/**
|
|
501
|
+
* `character` styles, `pro` bases only: a manifest-relative concept
|
|
502
|
+
* image (a painting, a photo, a sketch; up to 1024px) that seeds the
|
|
503
|
+
* design instead of the prompt alone. A style image or `styleCharacter`
|
|
504
|
+
* may still anchor the look.
|
|
505
|
+
*/
|
|
506
|
+
concept: z.string().min(1).optional(),
|
|
507
|
+
/** `character` styles, `pro` bases: this base's style anchor, over the style's. */
|
|
508
|
+
styleCharacter: z.string().min(1).optional(),
|
|
481
509
|
/**
|
|
482
510
|
* Another asset of the same style flipped left to right, made locally
|
|
483
511
|
* from that asset's downloaded files at no generation cost.
|
|
@@ -559,6 +587,20 @@ var AssetSchema = z.object({
|
|
|
559
587
|
path: ["reference"]
|
|
560
588
|
});
|
|
561
589
|
}
|
|
590
|
+
if (asset.concept && (asset.state || asset.animation || asset.mirror)) {
|
|
591
|
+
context.addIssue({
|
|
592
|
+
code: z.ZodIssueCode.custom,
|
|
593
|
+
message: "a concept image belongs on a base; a state, animation, or mirror takes its look from its parent",
|
|
594
|
+
path: ["concept"]
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
if (asset.concept && asset.reference) {
|
|
598
|
+
context.addIssue({
|
|
599
|
+
code: z.ZodIssueCode.custom,
|
|
600
|
+
message: "concept and reference are mutually exclusive: a concept seeds a new design, a reference is the sprite to rotate",
|
|
601
|
+
path: ["concept"]
|
|
602
|
+
});
|
|
603
|
+
}
|
|
562
604
|
if (typeof asset.reference === "object" && !Object.keys(asset.reference).length) {
|
|
563
605
|
context.addIssue({ code: z.ZodIssueCode.custom, message: "a reference needs at least a south image", path: ["reference"] });
|
|
564
606
|
}
|
|
@@ -1233,6 +1275,29 @@ var PixelLabClient = class {
|
|
|
1233
1275
|
...south ? { reference_image: encode(south) } : {},
|
|
1234
1276
|
...args.enhancePrompt ? { enhance_prompt: true } : {}
|
|
1235
1277
|
};
|
|
1278
|
+
} else if (args.mode === "pro-flash") {
|
|
1279
|
+
path33 = "/create-character-pro-flash";
|
|
1280
|
+
const traits = args.styleTraits;
|
|
1281
|
+
body = {
|
|
1282
|
+
description: args.description,
|
|
1283
|
+
template_id: args.template,
|
|
1284
|
+
n_directions: 8,
|
|
1285
|
+
// The author's sprite sets the canvas; a size only applies to text creation.
|
|
1286
|
+
...south ? { first_frame: encode(south) } : { image_size: imageSize },
|
|
1287
|
+
...args.view ? { view: args.view } : {},
|
|
1288
|
+
...args.seed != null ? { seed: args.seed } : {},
|
|
1289
|
+
...args.styleReference && args.styleReferenceSize ? {
|
|
1290
|
+
style_image: { image: encode(args.styleReference), size: args.styleReferenceSize },
|
|
1291
|
+
...traits ? {
|
|
1292
|
+
style_options: {
|
|
1293
|
+
...traits.palette !== void 0 ? { color_palette: traits.palette } : {},
|
|
1294
|
+
...traits.outline !== void 0 ? { outline: traits.outline } : {},
|
|
1295
|
+
...traits.detail !== void 0 ? { detail: traits.detail } : {},
|
|
1296
|
+
...traits.shading !== void 0 ? { shading: traits.shading } : {}
|
|
1297
|
+
}
|
|
1298
|
+
} : {}
|
|
1299
|
+
} : {}
|
|
1300
|
+
};
|
|
1236
1301
|
} else if (args.mode === "pro") {
|
|
1237
1302
|
path33 = "/create-character-pro";
|
|
1238
1303
|
body = {
|
|
@@ -1240,10 +1305,12 @@ var PixelLabClient = class {
|
|
|
1240
1305
|
image_size: imageSize,
|
|
1241
1306
|
template_id: args.template,
|
|
1242
1307
|
no_background: args.noBackground ?? true,
|
|
1243
|
-
method: south ? "rotate_character" : "create_with_style",
|
|
1308
|
+
method: south ? "rotate_character" : args.concept ? "create_from_concept" : "create_with_style",
|
|
1244
1309
|
...args.view ? { view: args.view } : {},
|
|
1245
1310
|
...args.seed != null ? { seed: args.seed } : {},
|
|
1246
|
-
...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {}
|
|
1311
|
+
...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {},
|
|
1312
|
+
...!south && args.concept ? { concept_image: encode(args.concept) } : {},
|
|
1313
|
+
...!south && args.styleCharacterId ? { style_character_id: args.styleCharacterId } : {}
|
|
1247
1314
|
};
|
|
1248
1315
|
} else {
|
|
1249
1316
|
path33 = args.directions === 4 ? "/create-character-with-4-directions" : "/create-character-with-8-directions";
|
|
@@ -2005,7 +2072,10 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
2005
2072
|
textGuidanceScale: spec.character.textGuidanceScale,
|
|
2006
2073
|
isometric: spec.character.isometric,
|
|
2007
2074
|
enhancePrompt: spec.character.enhancePrompt,
|
|
2008
|
-
|
|
2075
|
+
styleTraits: spec.character.styleTraits,
|
|
2076
|
+
reference: spec.character.reference ? Object.fromEntries(Object.entries(spec.character.reference).map(([direction, image]) => [direction, image.sha256])) : void 0,
|
|
2077
|
+
concept: spec.character.concept?.sha256,
|
|
2078
|
+
styleAnchor: spec.character.styleAnchor ? { of: spec.character.styleAnchor.assetId, sha256: spec.character.styleAnchor.sha256 } : void 0
|
|
2009
2079
|
} : void 0,
|
|
2010
2080
|
// A mirror's bytes come from its source's recorded outputs; the plan
|
|
2011
2081
|
// compares those directly, so only the choice of source is identity.
|
|
@@ -2046,12 +2116,24 @@ function characterCost(spec) {
|
|
|
2046
2116
|
if (character.kind === "state") return generationCost(spec.width, spec.height, "1dir");
|
|
2047
2117
|
if (character.mode === "standard") return 1;
|
|
2048
2118
|
if (character.mode === "v3") return 1 + Math.max(1, Math.ceil(px * 8 / 65536));
|
|
2119
|
+
if (character.mode === "pro-flash") {
|
|
2120
|
+
const south = character.reference?.south;
|
|
2121
|
+
return south ? proFlashCharacterCost(south.width, south.height, true) : proFlashCharacterCost(spec.width, spec.height, false);
|
|
2122
|
+
}
|
|
2049
2123
|
return generationCost(spec.width, spec.height, "1dir");
|
|
2050
2124
|
}
|
|
2125
|
+
function proFlashCharacterCost(width, height, fromReference) {
|
|
2126
|
+
const side = Math.max(32, Math.ceil(Math.max(width, height) / 4) * 4);
|
|
2127
|
+
const rotations = Math.max(1, Math.ceil(side * side * 8 / 65536));
|
|
2128
|
+
if (fromReference) return rotations;
|
|
2129
|
+
const image = side <= 96 ? 5 : side <= 208 ? 6 : 9;
|
|
2130
|
+
return image + rotations;
|
|
2131
|
+
}
|
|
2051
2132
|
function characterAnimationName(spec) {
|
|
2052
2133
|
return `pixelkiln:${spec.styleId}/${spec.assetId}`;
|
|
2053
2134
|
}
|
|
2054
2135
|
var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
|
|
2136
|
+
var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
|
|
2055
2137
|
function encodeAnimationJob(job) {
|
|
2056
2138
|
return `character-animation:${Buffer.from(JSON.stringify(job)).toString("base64url")}`;
|
|
2057
2139
|
}
|
|
@@ -2192,12 +2274,25 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2192
2274
|
}
|
|
2193
2275
|
}
|
|
2194
2276
|
}
|
|
2277
|
+
if (character.concept) {
|
|
2278
|
+
if (character.mode !== "pro") throw new Error(`${label}: a concept image is a pro input; the ${character.mode} engine draws from text or a reference`);
|
|
2279
|
+
if (character.concept.width > 1024 || character.concept.height > 1024) {
|
|
2280
|
+
throw new Error(`${label}: concept image is ${character.concept.width}x${character.concept.height}; PixelLab pro takes up to 1024px`);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
if (character.styleAnchor) {
|
|
2284
|
+
if (character.mode !== "pro") throw new Error(`${label}: styleCharacter is a pro input; the ${character.mode} engine has no style anchor`);
|
|
2285
|
+
if (character.reference) throw new Error(`${label}: a pro base rotating its own reference takes no styleCharacter`);
|
|
2286
|
+
if (character.styleAnchor.spec.character?.directions !== 8) {
|
|
2287
|
+
throw new Error(`${label}: styleCharacter ${character.styleAnchor.assetId} has ${character.styleAnchor.spec.character?.directions} directions; PixelLab wants an 8-direction anchor`);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2195
2290
|
if (character.reference) {
|
|
2196
2291
|
const given = Object.keys(character.reference);
|
|
2197
2292
|
if (!character.reference.south) throw new Error(`${label}: a reference needs a south-facing sprite`);
|
|
2198
2293
|
if (character.mode !== "standard") {
|
|
2199
2294
|
if (given.length > 1) throw new Error(`${label}: PixelLab ${character.mode} rotates one south-facing reference; drop the other directions`);
|
|
2200
|
-
const limit = character.mode === "
|
|
2295
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
2201
2296
|
const south = character.reference.south;
|
|
2202
2297
|
if (south.width > limit || south.height > limit) {
|
|
2203
2298
|
throw new Error(`${label}: reference is ${south.width}x${south.height}; PixelLab ${character.mode} takes up to ${limit}px`);
|
|
@@ -2221,26 +2316,39 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2221
2316
|
}
|
|
2222
2317
|
}
|
|
2223
2318
|
if (styleImages.length) {
|
|
2224
|
-
if (character.mode !== "pro") {
|
|
2319
|
+
if (character.mode !== "pro" && character.mode !== "pro-flash") {
|
|
2225
2320
|
throw new Error(
|
|
2226
|
-
`PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro for a style anchor`
|
|
2321
|
+
`PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro or pro-flash for a style anchor`
|
|
2227
2322
|
);
|
|
2228
2323
|
}
|
|
2229
|
-
if (styleImages.length > 1) throw new Error(
|
|
2324
|
+
if (styleImages.length > 1) throw new Error(`PixelLab ${character.mode} characters take one style image`);
|
|
2230
2325
|
if (character.kind === "base" && character.reference) {
|
|
2231
|
-
throw new Error(`${label}: a
|
|
2326
|
+
throw new Error(`${label}: a ${character.mode} base rotating its own reference takes no style image`);
|
|
2232
2327
|
}
|
|
2233
2328
|
const image = styleImages[0];
|
|
2234
|
-
|
|
2235
|
-
|
|
2329
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
2330
|
+
if (image.width > limit || image.height > limit) {
|
|
2331
|
+
throw new Error(`PixelLab ${character.mode} character style image is ${image.width}x${image.height}; the limit is ${limit}px`);
|
|
2332
|
+
}
|
|
2333
|
+
if (character.mode === "pro-flash" && (image.width > spec.width || image.height > spec.height)) {
|
|
2334
|
+
throw new Error(
|
|
2335
|
+
`PixelLab pro-flash style image is ${image.width}x${image.height} but the character is ${spec.width}x${spec.height}; crop the image to its subject or raise the style's size`
|
|
2336
|
+
);
|
|
2236
2337
|
}
|
|
2237
2338
|
}
|
|
2238
|
-
|
|
2339
|
+
if (character.styleTraits && character.mode !== "pro-flash") {
|
|
2340
|
+
throw new Error(`${label}: styleTraits choose what a pro-flash style image lends; the ${character.mode} engine does not take them`);
|
|
2341
|
+
}
|
|
2342
|
+
const maxSize = character.mode === "v3" || character.mode === "pro-flash" ? 256 : 128;
|
|
2239
2343
|
if (spec.width < 16 || spec.height < 16 || spec.width > maxSize || spec.height > maxSize) {
|
|
2240
2344
|
throw new Error(`PixelLab ${character.mode} characters must be between 16 and ${maxSize} pixels`);
|
|
2241
2345
|
}
|
|
2242
|
-
if (
|
|
2243
|
-
throw new Error(`PixelLab
|
|
2346
|
+
if (character.mode === "pro-flash" && character.kind === "base" && (spec.width % 4 || spec.height % 4)) {
|
|
2347
|
+
throw new Error(`PixelLab pro-flash characters are sized in multiples of 4 pixels; ${spec.width}x${spec.height} is not`);
|
|
2348
|
+
}
|
|
2349
|
+
const templates = character.mode === "pro-flash" ? PRO_FLASH_TEMPLATES : CHARACTER_TEMPLATES;
|
|
2350
|
+
if (!templates.includes(character.template)) {
|
|
2351
|
+
throw new Error(`PixelLab ${character.mode} character template must be one of: ${templates.join(", ")}`);
|
|
2244
2352
|
}
|
|
2245
2353
|
const views = character.mode === "standard" ? ["low top-down", "high top-down", "side", "perspective", "oblique"] : ["low top-down", "high top-down", "side"];
|
|
2246
2354
|
if (!views.includes(spec.view)) {
|
|
@@ -2293,7 +2401,11 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2293
2401
|
isometric: character.isometric,
|
|
2294
2402
|
reference: character.reference ? readReference(spec, character.reference) : void 0,
|
|
2295
2403
|
styleReference: styleImage ? { base64: styleImage.base64, format: styleImage.format } : void 0,
|
|
2296
|
-
enhancePrompt: character.enhancePrompt
|
|
2404
|
+
enhancePrompt: character.enhancePrompt,
|
|
2405
|
+
concept: character.concept ? readPose(spec, "concept image", character.concept) : void 0,
|
|
2406
|
+
styleCharacterId: character.styleAnchor ? requireStyleObjectId(spec, context) : void 0,
|
|
2407
|
+
styleReferenceSize: styleImage ? { width: styleImage.width, height: styleImage.height } : void 0,
|
|
2408
|
+
styleTraits: character.styleTraits
|
|
2297
2409
|
});
|
|
2298
2410
|
return { jobId: res2.character_id, metadata: { character: { kind: "base", characterId: res2.character_id, mode: character.mode, directions: character.directions, backgroundJobId: res2.background_job_id } } };
|
|
2299
2411
|
}
|
|
@@ -2713,6 +2825,14 @@ function readReference(spec, reference) {
|
|
|
2713
2825
|
}
|
|
2714
2826
|
return images;
|
|
2715
2827
|
}
|
|
2828
|
+
function requireStyleObjectId(spec, context) {
|
|
2829
|
+
if (!context?.styleObjectId) {
|
|
2830
|
+
throw new Error(
|
|
2831
|
+
`${spec.styleId}/${spec.assetId} anchors its style on ${spec.character.styleAnchor.assetId}, which has no PixelLab character id in the lockfile yet; generate the anchor first`
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2834
|
+
return context.styleObjectId;
|
|
2835
|
+
}
|
|
2716
2836
|
function readPose(spec, what, image) {
|
|
2717
2837
|
const bytes = readFileSync(image.path);
|
|
2718
2838
|
if (sha256(bytes) !== image.sha256) {
|
|
@@ -5412,6 +5532,18 @@ async function resolveSpecs(loaded, filter) {
|
|
|
5412
5532
|
finalized.add(assetId);
|
|
5413
5533
|
return resolved;
|
|
5414
5534
|
}
|
|
5535
|
+
const anchorId = asset.styleCharacter ?? style.styleCharacter;
|
|
5536
|
+
if (resolved.character?.kind === "base" && anchorId && anchorId !== assetId) {
|
|
5537
|
+
const anchorSpec = await finalize(anchorId);
|
|
5538
|
+
if (!anchorSpec.character || anchorSpec.character.kind === "animation") {
|
|
5539
|
+
throw new Error(`assets.${assetId}: styleCharacter ${anchorId} is not a character base or state`);
|
|
5540
|
+
}
|
|
5541
|
+
const file = memberPath(anchorSpec.outFile, "south", 0, anchorSpec.character.directions, MediaType.PNG);
|
|
5542
|
+
resolved.character = {
|
|
5543
|
+
...resolved.character,
|
|
5544
|
+
styleAnchor: { assetId: anchorId, spec: anchorSpec, file, sha256: existsSync4(file) ? await sha256File(file) : null }
|
|
5545
|
+
};
|
|
5546
|
+
}
|
|
5415
5547
|
const characterParent = asset.state?.of ?? asset.animation?.of;
|
|
5416
5548
|
if (resolved.character && characterParent) {
|
|
5417
5549
|
const parentSpec = await finalize(characterParent);
|
|
@@ -5562,8 +5694,13 @@ async function resolveCharacterShape(asset, style, kind, files) {
|
|
|
5562
5694
|
...proportions !== void 0 ? { proportions } : {},
|
|
5563
5695
|
...style.textGuidanceScale !== void 0 ? { textGuidanceScale: style.textGuidanceScale } : {},
|
|
5564
5696
|
...style.isometric !== void 0 ? { isometric: style.isometric } : {},
|
|
5565
|
-
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {}
|
|
5697
|
+
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {},
|
|
5698
|
+
...style.styleTraits ? { styleTraits: style.styleTraits } : {}
|
|
5566
5699
|
};
|
|
5700
|
+
if (asset.concept) {
|
|
5701
|
+
const image = await files.load(asset.concept, "Concept image");
|
|
5702
|
+
shape.concept = { path: path5.resolve(files.root, asset.concept), sha256: image.hash, width: image.width, height: image.height, format: image.format };
|
|
5703
|
+
}
|
|
5567
5704
|
if (asset.reference) {
|
|
5568
5705
|
const byDirection = typeof asset.reference === "string" ? { south: asset.reference } : asset.reference;
|
|
5569
5706
|
shape.reference = {};
|
|
@@ -7083,9 +7220,24 @@ import path11 from "path";
|
|
|
7083
7220
|
async function inspectRevisionReadiness(spec, lock) {
|
|
7084
7221
|
if (spec.mirror) return inspectMirror(spec, lock, /* @__PURE__ */ new Set());
|
|
7085
7222
|
if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
|
|
7223
|
+
if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
|
|
7086
7224
|
if (!spec.revision) return null;
|
|
7087
7225
|
return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
|
|
7088
7226
|
}
|
|
7227
|
+
async function inspectStyleAnchor(spec, lock, seen) {
|
|
7228
|
+
const anchor = spec.character.styleAnchor;
|
|
7229
|
+
const label = `style anchor ${spec.styleId}/${anchor.assetId}`;
|
|
7230
|
+
const dependency = await inspectParent(anchor.spec, lock, seen);
|
|
7231
|
+
if (!dependency.ready) return { ready: false, reason: `${label} is not ready: ${dependency.reason}` };
|
|
7232
|
+
if (!anchor.sha256 || !existsSync7(anchor.file)) return { ready: false, reason: `${label} has no generated south-facing file yet` };
|
|
7233
|
+
if (await sha256File(anchor.file) !== anchor.sha256) {
|
|
7234
|
+
return { ready: false, reason: `${label} changed after the manifest was resolved` };
|
|
7235
|
+
}
|
|
7236
|
+
if (!lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)]?.objectId) {
|
|
7237
|
+
return { ready: false, reason: `${label} has no PixelLab character id recorded` };
|
|
7238
|
+
}
|
|
7239
|
+
return { ready: true, reason: `${label} is current` };
|
|
7240
|
+
}
|
|
7089
7241
|
async function inspectMirror(spec, lock, seen) {
|
|
7090
7242
|
const source = spec.mirror.sourceSpec;
|
|
7091
7243
|
const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
|
|
@@ -7157,6 +7309,10 @@ async function inspectParent(spec, lock, seen) {
|
|
|
7157
7309
|
const inputs = await inspectCharacterParent(spec, lock, nextSeen);
|
|
7158
7310
|
if (!inputs.ready) return inputs;
|
|
7159
7311
|
}
|
|
7312
|
+
if (spec.character?.styleAnchor) {
|
|
7313
|
+
const inputs = await inspectStyleAnchor(spec, lock, nextSeen);
|
|
7314
|
+
if (!inputs.ready) return inputs;
|
|
7315
|
+
}
|
|
7160
7316
|
if (spec.quality) {
|
|
7161
7317
|
const quality = await inspectQualityProfile(spec, lock);
|
|
7162
7318
|
return quality?.state === "approved" ? { ready: true, reason: "approved quality output is current" } : {
|
|
@@ -7196,6 +7352,14 @@ async function anyOutputModified(entry, spec) {
|
|
|
7196
7352
|
}
|
|
7197
7353
|
return false;
|
|
7198
7354
|
}
|
|
7355
|
+
function dependencies(spec) {
|
|
7356
|
+
return [
|
|
7357
|
+
spec.mirror?.sourceSpec,
|
|
7358
|
+
spec.revision?.sourceSpec,
|
|
7359
|
+
spec.character?.parentSpec,
|
|
7360
|
+
spec.character?.styleAnchor?.spec
|
|
7361
|
+
].filter((parent) => Boolean(parent));
|
|
7362
|
+
}
|
|
7199
7363
|
function resumeCommandForStatus(status) {
|
|
7200
7364
|
if (status === "pending" || status === "processing") return "poll";
|
|
7201
7365
|
if (status === "review") return "pick";
|
|
@@ -7304,16 +7468,19 @@ async function buildPlan(specs, lock, opts = {}) {
|
|
|
7304
7468
|
const stateOf = new Map(items.map((i) => [i.key, i.state]));
|
|
7305
7469
|
for (const item of items) {
|
|
7306
7470
|
if (!isActionable(item)) continue;
|
|
7307
|
-
const parent
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
item.
|
|
7316
|
-
|
|
7471
|
+
for (const parent of dependencies(item.spec)) {
|
|
7472
|
+
const parentKey = lockKey(parent.styleId, parent.assetId);
|
|
7473
|
+
const parentState = stateOf.get(parentKey);
|
|
7474
|
+
if (parentState && isActionable({ state: parentState })) {
|
|
7475
|
+
item.state = "blocked";
|
|
7476
|
+
item.reason = `parent ${parentKey} is being generated in this run; this follows in the next wave`;
|
|
7477
|
+
break;
|
|
7478
|
+
}
|
|
7479
|
+
if (item.spec.mirror && (parentState === "recoverable" || parentState === "in-flight")) {
|
|
7480
|
+
item.state = "blocked";
|
|
7481
|
+
item.reason = `mirror source ${parentKey} is ${parentState}; this follows in the next wave`;
|
|
7482
|
+
break;
|
|
7483
|
+
}
|
|
7317
7484
|
}
|
|
7318
7485
|
}
|
|
7319
7486
|
const actionable = items.filter(isActionable);
|
|
@@ -9792,10 +9959,13 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
|
|
|
9792
9959
|
try {
|
|
9793
9960
|
const refs = styleImages.get(spec.styleId) ?? [];
|
|
9794
9961
|
const parentEntry = spec.character?.parentSpec ? lock.entries[lockKey(spec.character.parentSpec.styleId, spec.character.parentSpec.assetId)] : void 0;
|
|
9962
|
+
const anchor = spec.character?.styleAnchor;
|
|
9963
|
+
const anchorEntry = anchor ? lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)] : void 0;
|
|
9795
9964
|
const replacedMetadata = previousEntry?.providerMetadata?.[provider.id];
|
|
9796
9965
|
const { jobId, metadata } = await provider.submit(spec, refs, {
|
|
9797
9966
|
...previousJobId ? { previousJobId } : {},
|
|
9798
9967
|
...parentEntry?.objectId ? { parentObjectId: parentEntry.objectId } : {},
|
|
9968
|
+
...anchorEntry?.objectId ? { styleObjectId: anchorEntry.objectId } : {},
|
|
9799
9969
|
...replacedMetadata ? { replacedMetadata } : {},
|
|
9800
9970
|
...previousMetadata ? { previousMetadata } : {},
|
|
9801
9971
|
checkpoint: async (checkpoint) => {
|
|
@@ -12404,7 +12574,7 @@ var pin_default = {
|
|
|
12404
12574
|
godot: "4.7.2",
|
|
12405
12575
|
extensionsApi: 9,
|
|
12406
12576
|
protocol: 4,
|
|
12407
|
-
release: "editor-pixelorama-v1.2.2-pk.
|
|
12577
|
+
release: "editor-pixelorama-v1.2.2-pk.26",
|
|
12408
12578
|
files: {
|
|
12409
12579
|
"index.apple-touch-icon.png": {
|
|
12410
12580
|
sha256: "ee5434873e0fed91e9a888c3ea5a8b79beac25999308be7a6eb41bf4ce640d27",
|
|
@@ -12419,7 +12589,7 @@ var pin_default = {
|
|
|
12419
12589
|
bytes: 7298
|
|
12420
12590
|
},
|
|
12421
12591
|
"index.html": {
|
|
12422
|
-
sha256: "
|
|
12592
|
+
sha256: "326101ab02bb4a29a7964214c9307c7dff26e9d66b8ebaaf6e7a3987e84a05b2",
|
|
12423
12593
|
bytes: 5442
|
|
12424
12594
|
},
|
|
12425
12595
|
"index.icon.png": {
|
|
@@ -12431,8 +12601,8 @@ var pin_default = {
|
|
|
12431
12601
|
bytes: 279815
|
|
12432
12602
|
},
|
|
12433
12603
|
"index.pck": {
|
|
12434
|
-
sha256: "
|
|
12435
|
-
bytes:
|
|
12604
|
+
sha256: "e26292650bb996965acd1ba70e74d2b4020b063d14f1276701312c1d34cb0a83",
|
|
12605
|
+
bytes: 6431932
|
|
12436
12606
|
},
|
|
12437
12607
|
"index.png": {
|
|
12438
12608
|
sha256: "6e3ca3eb4a99e4c07bdd89ebc873b440ec0ffd66ce1955160da9e7ed80d538d7",
|