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.cjs
CHANGED
|
@@ -389,7 +389,7 @@ var MIRRORED_DIRECTION = {
|
|
|
389
389
|
west: "east",
|
|
390
390
|
"south-west": "south-east"
|
|
391
391
|
};
|
|
392
|
-
var CharacterModeSchema = import_zod.z.enum(["standard", "v3", "pro"]);
|
|
392
|
+
var CharacterModeSchema = import_zod.z.enum(["standard", "v3", "pro", "pro-flash"]);
|
|
393
393
|
var CHARACTER_PROPORTION_PRESETS = ["default", "chibi", "cartoon", "stylized", "realistic_male", "realistic_female", "heroic"];
|
|
394
394
|
var CharacterProportionsSchema = import_zod.z.union([
|
|
395
395
|
import_zod.z.enum(CHARACTER_PROPORTION_PRESETS),
|
|
@@ -585,14 +585,27 @@ var StyleObjectSchema = import_zod.z.object({
|
|
|
585
585
|
/**
|
|
586
586
|
* `character` only. `standard` draws from a skeleton template for 1
|
|
587
587
|
* generation; `v3` is the highest quality at 2 to 9 by size; `pro` is a
|
|
588
|
-
* reference-based engine at 20 to 40 by size
|
|
589
|
-
*
|
|
588
|
+
* reference-based engine at 20 to 40 by size; `pro-flash` draws a
|
|
589
|
+
* south sprite with PixelLab's newest image model and rotates it with
|
|
590
|
+
* v3, 6 to 17 by size, or the rotations alone (1 at 64px) from a
|
|
591
|
+
* `reference`. States inherit the parent's engine; animations choose
|
|
592
|
+
* their own.
|
|
590
593
|
*/
|
|
591
594
|
mode: CharacterModeSchema.optional(),
|
|
592
|
-
/** `character` only. Rotations per base or state.
|
|
595
|
+
/** `character` only. Rotations per base or state. Every engine but `standard` draws 8. */
|
|
593
596
|
directions: import_zod.z.union([import_zod.z.literal(4), import_zod.z.literal(8)]).optional(),
|
|
594
|
-
/** `character` only. Body template: `mannequin` (default)
|
|
597
|
+
/** `character` only. Body template: `mannequin` (default), a quadruped (`bear`, `cat`, `dog`, `horse`, `lion`), or `custom` for `pro-flash`. */
|
|
595
598
|
template: import_zod.z.string().min(1).optional(),
|
|
599
|
+
/**
|
|
600
|
+
* `character` only, `pro-flash` bases with a style image: which traits
|
|
601
|
+
* the style image lends. Each defaults to true.
|
|
602
|
+
*/
|
|
603
|
+
styleTraits: import_zod.z.object({
|
|
604
|
+
palette: import_zod.z.boolean().optional(),
|
|
605
|
+
outline: import_zod.z.boolean().optional(),
|
|
606
|
+
detail: import_zod.z.boolean().optional(),
|
|
607
|
+
shading: import_zod.z.boolean().optional()
|
|
608
|
+
}).strict().optional(),
|
|
596
609
|
/** `character` only, `standard` humanoid bases. A preset or multipliers; an asset may override it. */
|
|
597
610
|
proportions: CharacterProportionsSchema.optional(),
|
|
598
611
|
/**
|
|
@@ -605,6 +618,12 @@ var StyleObjectSchema = import_zod.z.object({
|
|
|
605
618
|
isometric: import_zod.z.boolean().optional(),
|
|
606
619
|
/** `character` only, `v3` bases: let PixelLab expand the prompt into a fuller one before drawing. */
|
|
607
620
|
enhancePrompt: import_zod.z.boolean().optional(),
|
|
621
|
+
/**
|
|
622
|
+
* `character` only, `pro` bases: the asset id of a generated 8-direction
|
|
623
|
+
* character in this style whose look every base drawn from text or a
|
|
624
|
+
* concept follows. An asset may override it; the anchor itself ignores it.
|
|
625
|
+
*/
|
|
626
|
+
styleCharacter: import_zod.z.string().min(1).optional(),
|
|
608
627
|
/** Fixed seed for reproducibility where the endpoint supports it. */
|
|
609
628
|
seed: import_zod.z.number().int().optional(),
|
|
610
629
|
/**
|
|
@@ -777,6 +796,15 @@ var AssetSchema = import_zod.z.object({
|
|
|
777
796
|
* still guides the result.
|
|
778
797
|
*/
|
|
779
798
|
reference: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.record(CharacterDirectionSchema, import_zod.z.string().min(1))]).optional(),
|
|
799
|
+
/**
|
|
800
|
+
* `character` styles, `pro` bases only: a manifest-relative concept
|
|
801
|
+
* image (a painting, a photo, a sketch; up to 1024px) that seeds the
|
|
802
|
+
* design instead of the prompt alone. A style image or `styleCharacter`
|
|
803
|
+
* may still anchor the look.
|
|
804
|
+
*/
|
|
805
|
+
concept: import_zod.z.string().min(1).optional(),
|
|
806
|
+
/** `character` styles, `pro` bases: this base's style anchor, over the style's. */
|
|
807
|
+
styleCharacter: import_zod.z.string().min(1).optional(),
|
|
780
808
|
/**
|
|
781
809
|
* Another asset of the same style flipped left to right, made locally
|
|
782
810
|
* from that asset's downloaded files at no generation cost.
|
|
@@ -858,6 +886,20 @@ var AssetSchema = import_zod.z.object({
|
|
|
858
886
|
path: ["reference"]
|
|
859
887
|
});
|
|
860
888
|
}
|
|
889
|
+
if (asset.concept && (asset.state || asset.animation || asset.mirror)) {
|
|
890
|
+
context.addIssue({
|
|
891
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
892
|
+
message: "a concept image belongs on a base; a state, animation, or mirror takes its look from its parent",
|
|
893
|
+
path: ["concept"]
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
if (asset.concept && asset.reference) {
|
|
897
|
+
context.addIssue({
|
|
898
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
899
|
+
message: "concept and reference are mutually exclusive: a concept seeds a new design, a reference is the sprite to rotate",
|
|
900
|
+
path: ["concept"]
|
|
901
|
+
});
|
|
902
|
+
}
|
|
861
903
|
if (typeof asset.reference === "object" && !Object.keys(asset.reference).length) {
|
|
862
904
|
context.addIssue({ code: import_zod.z.ZodIssueCode.custom, message: "a reference needs at least a south image", path: ["reference"] });
|
|
863
905
|
}
|
|
@@ -1532,6 +1574,29 @@ var PixelLabClient = class {
|
|
|
1532
1574
|
...south ? { reference_image: encode(south) } : {},
|
|
1533
1575
|
...args.enhancePrompt ? { enhance_prompt: true } : {}
|
|
1534
1576
|
};
|
|
1577
|
+
} else if (args.mode === "pro-flash") {
|
|
1578
|
+
path33 = "/create-character-pro-flash";
|
|
1579
|
+
const traits = args.styleTraits;
|
|
1580
|
+
body = {
|
|
1581
|
+
description: args.description,
|
|
1582
|
+
template_id: args.template,
|
|
1583
|
+
n_directions: 8,
|
|
1584
|
+
// The author's sprite sets the canvas; a size only applies to text creation.
|
|
1585
|
+
...south ? { first_frame: encode(south) } : { image_size: imageSize },
|
|
1586
|
+
...args.view ? { view: args.view } : {},
|
|
1587
|
+
...args.seed != null ? { seed: args.seed } : {},
|
|
1588
|
+
...args.styleReference && args.styleReferenceSize ? {
|
|
1589
|
+
style_image: { image: encode(args.styleReference), size: args.styleReferenceSize },
|
|
1590
|
+
...traits ? {
|
|
1591
|
+
style_options: {
|
|
1592
|
+
...traits.palette !== void 0 ? { color_palette: traits.palette } : {},
|
|
1593
|
+
...traits.outline !== void 0 ? { outline: traits.outline } : {},
|
|
1594
|
+
...traits.detail !== void 0 ? { detail: traits.detail } : {},
|
|
1595
|
+
...traits.shading !== void 0 ? { shading: traits.shading } : {}
|
|
1596
|
+
}
|
|
1597
|
+
} : {}
|
|
1598
|
+
} : {}
|
|
1599
|
+
};
|
|
1535
1600
|
} else if (args.mode === "pro") {
|
|
1536
1601
|
path33 = "/create-character-pro";
|
|
1537
1602
|
body = {
|
|
@@ -1539,10 +1604,12 @@ var PixelLabClient = class {
|
|
|
1539
1604
|
image_size: imageSize,
|
|
1540
1605
|
template_id: args.template,
|
|
1541
1606
|
no_background: args.noBackground ?? true,
|
|
1542
|
-
method: south ? "rotate_character" : "create_with_style",
|
|
1607
|
+
method: south ? "rotate_character" : args.concept ? "create_from_concept" : "create_with_style",
|
|
1543
1608
|
...args.view ? { view: args.view } : {},
|
|
1544
1609
|
...args.seed != null ? { seed: args.seed } : {},
|
|
1545
|
-
...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {}
|
|
1610
|
+
...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {},
|
|
1611
|
+
...!south && args.concept ? { concept_image: encode(args.concept) } : {},
|
|
1612
|
+
...!south && args.styleCharacterId ? { style_character_id: args.styleCharacterId } : {}
|
|
1546
1613
|
};
|
|
1547
1614
|
} else {
|
|
1548
1615
|
path33 = args.directions === 4 ? "/create-character-with-4-directions" : "/create-character-with-8-directions";
|
|
@@ -2304,7 +2371,10 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
2304
2371
|
textGuidanceScale: spec.character.textGuidanceScale,
|
|
2305
2372
|
isometric: spec.character.isometric,
|
|
2306
2373
|
enhancePrompt: spec.character.enhancePrompt,
|
|
2307
|
-
|
|
2374
|
+
styleTraits: spec.character.styleTraits,
|
|
2375
|
+
reference: spec.character.reference ? Object.fromEntries(Object.entries(spec.character.reference).map(([direction, image]) => [direction, image.sha256])) : void 0,
|
|
2376
|
+
concept: spec.character.concept?.sha256,
|
|
2377
|
+
styleAnchor: spec.character.styleAnchor ? { of: spec.character.styleAnchor.assetId, sha256: spec.character.styleAnchor.sha256 } : void 0
|
|
2308
2378
|
} : void 0,
|
|
2309
2379
|
// A mirror's bytes come from its source's recorded outputs; the plan
|
|
2310
2380
|
// compares those directly, so only the choice of source is identity.
|
|
@@ -2345,12 +2415,24 @@ function characterCost(spec) {
|
|
|
2345
2415
|
if (character.kind === "state") return generationCost(spec.width, spec.height, "1dir");
|
|
2346
2416
|
if (character.mode === "standard") return 1;
|
|
2347
2417
|
if (character.mode === "v3") return 1 + Math.max(1, Math.ceil(px * 8 / 65536));
|
|
2418
|
+
if (character.mode === "pro-flash") {
|
|
2419
|
+
const south = character.reference?.south;
|
|
2420
|
+
return south ? proFlashCharacterCost(south.width, south.height, true) : proFlashCharacterCost(spec.width, spec.height, false);
|
|
2421
|
+
}
|
|
2348
2422
|
return generationCost(spec.width, spec.height, "1dir");
|
|
2349
2423
|
}
|
|
2424
|
+
function proFlashCharacterCost(width, height, fromReference) {
|
|
2425
|
+
const side = Math.max(32, Math.ceil(Math.max(width, height) / 4) * 4);
|
|
2426
|
+
const rotations = Math.max(1, Math.ceil(side * side * 8 / 65536));
|
|
2427
|
+
if (fromReference) return rotations;
|
|
2428
|
+
const image = side <= 96 ? 5 : side <= 208 ? 6 : 9;
|
|
2429
|
+
return image + rotations;
|
|
2430
|
+
}
|
|
2350
2431
|
function characterAnimationName(spec) {
|
|
2351
2432
|
return `pixelkiln:${spec.styleId}/${spec.assetId}`;
|
|
2352
2433
|
}
|
|
2353
2434
|
var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
|
|
2435
|
+
var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
|
|
2354
2436
|
function encodeAnimationJob(job) {
|
|
2355
2437
|
return `character-animation:${Buffer.from(JSON.stringify(job)).toString("base64url")}`;
|
|
2356
2438
|
}
|
|
@@ -2491,12 +2573,25 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2491
2573
|
}
|
|
2492
2574
|
}
|
|
2493
2575
|
}
|
|
2576
|
+
if (character.concept) {
|
|
2577
|
+
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`);
|
|
2578
|
+
if (character.concept.width > 1024 || character.concept.height > 1024) {
|
|
2579
|
+
throw new Error(`${label}: concept image is ${character.concept.width}x${character.concept.height}; PixelLab pro takes up to 1024px`);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
if (character.styleAnchor) {
|
|
2583
|
+
if (character.mode !== "pro") throw new Error(`${label}: styleCharacter is a pro input; the ${character.mode} engine has no style anchor`);
|
|
2584
|
+
if (character.reference) throw new Error(`${label}: a pro base rotating its own reference takes no styleCharacter`);
|
|
2585
|
+
if (character.styleAnchor.spec.character?.directions !== 8) {
|
|
2586
|
+
throw new Error(`${label}: styleCharacter ${character.styleAnchor.assetId} has ${character.styleAnchor.spec.character?.directions} directions; PixelLab wants an 8-direction anchor`);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2494
2589
|
if (character.reference) {
|
|
2495
2590
|
const given = Object.keys(character.reference);
|
|
2496
2591
|
if (!character.reference.south) throw new Error(`${label}: a reference needs a south-facing sprite`);
|
|
2497
2592
|
if (character.mode !== "standard") {
|
|
2498
2593
|
if (given.length > 1) throw new Error(`${label}: PixelLab ${character.mode} rotates one south-facing reference; drop the other directions`);
|
|
2499
|
-
const limit = character.mode === "
|
|
2594
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
2500
2595
|
const south = character.reference.south;
|
|
2501
2596
|
if (south.width > limit || south.height > limit) {
|
|
2502
2597
|
throw new Error(`${label}: reference is ${south.width}x${south.height}; PixelLab ${character.mode} takes up to ${limit}px`);
|
|
@@ -2520,26 +2615,39 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2520
2615
|
}
|
|
2521
2616
|
}
|
|
2522
2617
|
if (styleImages.length) {
|
|
2523
|
-
if (character.mode !== "pro") {
|
|
2618
|
+
if (character.mode !== "pro" && character.mode !== "pro-flash") {
|
|
2524
2619
|
throw new Error(
|
|
2525
|
-
`PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro for a style anchor`
|
|
2620
|
+
`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`
|
|
2526
2621
|
);
|
|
2527
2622
|
}
|
|
2528
|
-
if (styleImages.length > 1) throw new Error(
|
|
2623
|
+
if (styleImages.length > 1) throw new Error(`PixelLab ${character.mode} characters take one style image`);
|
|
2529
2624
|
if (character.kind === "base" && character.reference) {
|
|
2530
|
-
throw new Error(`${label}: a
|
|
2625
|
+
throw new Error(`${label}: a ${character.mode} base rotating its own reference takes no style image`);
|
|
2531
2626
|
}
|
|
2532
2627
|
const image = styleImages[0];
|
|
2533
|
-
|
|
2534
|
-
|
|
2628
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
2629
|
+
if (image.width > limit || image.height > limit) {
|
|
2630
|
+
throw new Error(`PixelLab ${character.mode} character style image is ${image.width}x${image.height}; the limit is ${limit}px`);
|
|
2631
|
+
}
|
|
2632
|
+
if (character.mode === "pro-flash" && (image.width > spec.width || image.height > spec.height)) {
|
|
2633
|
+
throw new Error(
|
|
2634
|
+
`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`
|
|
2635
|
+
);
|
|
2535
2636
|
}
|
|
2536
2637
|
}
|
|
2537
|
-
|
|
2638
|
+
if (character.styleTraits && character.mode !== "pro-flash") {
|
|
2639
|
+
throw new Error(`${label}: styleTraits choose what a pro-flash style image lends; the ${character.mode} engine does not take them`);
|
|
2640
|
+
}
|
|
2641
|
+
const maxSize = character.mode === "v3" || character.mode === "pro-flash" ? 256 : 128;
|
|
2538
2642
|
if (spec.width < 16 || spec.height < 16 || spec.width > maxSize || spec.height > maxSize) {
|
|
2539
2643
|
throw new Error(`PixelLab ${character.mode} characters must be between 16 and ${maxSize} pixels`);
|
|
2540
2644
|
}
|
|
2541
|
-
if (
|
|
2542
|
-
throw new Error(`PixelLab
|
|
2645
|
+
if (character.mode === "pro-flash" && character.kind === "base" && (spec.width % 4 || spec.height % 4)) {
|
|
2646
|
+
throw new Error(`PixelLab pro-flash characters are sized in multiples of 4 pixels; ${spec.width}x${spec.height} is not`);
|
|
2647
|
+
}
|
|
2648
|
+
const templates = character.mode === "pro-flash" ? PRO_FLASH_TEMPLATES : CHARACTER_TEMPLATES;
|
|
2649
|
+
if (!templates.includes(character.template)) {
|
|
2650
|
+
throw new Error(`PixelLab ${character.mode} character template must be one of: ${templates.join(", ")}`);
|
|
2543
2651
|
}
|
|
2544
2652
|
const views = character.mode === "standard" ? ["low top-down", "high top-down", "side", "perspective", "oblique"] : ["low top-down", "high top-down", "side"];
|
|
2545
2653
|
if (!views.includes(spec.view)) {
|
|
@@ -2592,7 +2700,11 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
2592
2700
|
isometric: character.isometric,
|
|
2593
2701
|
reference: character.reference ? readReference(spec, character.reference) : void 0,
|
|
2594
2702
|
styleReference: styleImage ? { base64: styleImage.base64, format: styleImage.format } : void 0,
|
|
2595
|
-
enhancePrompt: character.enhancePrompt
|
|
2703
|
+
enhancePrompt: character.enhancePrompt,
|
|
2704
|
+
concept: character.concept ? readPose(spec, "concept image", character.concept) : void 0,
|
|
2705
|
+
styleCharacterId: character.styleAnchor ? requireStyleObjectId(spec, context) : void 0,
|
|
2706
|
+
styleReferenceSize: styleImage ? { width: styleImage.width, height: styleImage.height } : void 0,
|
|
2707
|
+
styleTraits: character.styleTraits
|
|
2596
2708
|
});
|
|
2597
2709
|
return { jobId: res2.character_id, metadata: { character: { kind: "base", characterId: res2.character_id, mode: character.mode, directions: character.directions, backgroundJobId: res2.background_job_id } } };
|
|
2598
2710
|
}
|
|
@@ -3012,6 +3124,14 @@ function readReference(spec, reference) {
|
|
|
3012
3124
|
}
|
|
3013
3125
|
return images;
|
|
3014
3126
|
}
|
|
3127
|
+
function requireStyleObjectId(spec, context) {
|
|
3128
|
+
if (!context?.styleObjectId) {
|
|
3129
|
+
throw new Error(
|
|
3130
|
+
`${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`
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
return context.styleObjectId;
|
|
3134
|
+
}
|
|
3015
3135
|
function readPose(spec, what, image) {
|
|
3016
3136
|
const bytes = (0, import_node_fs2.readFileSync)(image.path);
|
|
3017
3137
|
if (sha256(bytes) !== image.sha256) {
|
|
@@ -5711,6 +5831,18 @@ async function resolveSpecs(loaded, filter) {
|
|
|
5711
5831
|
finalized.add(assetId);
|
|
5712
5832
|
return resolved;
|
|
5713
5833
|
}
|
|
5834
|
+
const anchorId = asset.styleCharacter ?? style.styleCharacter;
|
|
5835
|
+
if (resolved.character?.kind === "base" && anchorId && anchorId !== assetId) {
|
|
5836
|
+
const anchorSpec = await finalize(anchorId);
|
|
5837
|
+
if (!anchorSpec.character || anchorSpec.character.kind === "animation") {
|
|
5838
|
+
throw new Error(`assets.${assetId}: styleCharacter ${anchorId} is not a character base or state`);
|
|
5839
|
+
}
|
|
5840
|
+
const file = memberPath(anchorSpec.outFile, "south", 0, anchorSpec.character.directions, MediaType.PNG);
|
|
5841
|
+
resolved.character = {
|
|
5842
|
+
...resolved.character,
|
|
5843
|
+
styleAnchor: { assetId: anchorId, spec: anchorSpec, file, sha256: (0, import_node_fs5.existsSync)(file) ? await sha256File(file) : null }
|
|
5844
|
+
};
|
|
5845
|
+
}
|
|
5714
5846
|
const characterParent = asset.state?.of ?? asset.animation?.of;
|
|
5715
5847
|
if (resolved.character && characterParent) {
|
|
5716
5848
|
const parentSpec = await finalize(characterParent);
|
|
@@ -5861,8 +5993,13 @@ async function resolveCharacterShape(asset, style, kind, files) {
|
|
|
5861
5993
|
...proportions !== void 0 ? { proportions } : {},
|
|
5862
5994
|
...style.textGuidanceScale !== void 0 ? { textGuidanceScale: style.textGuidanceScale } : {},
|
|
5863
5995
|
...style.isometric !== void 0 ? { isometric: style.isometric } : {},
|
|
5864
|
-
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {}
|
|
5996
|
+
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {},
|
|
5997
|
+
...style.styleTraits ? { styleTraits: style.styleTraits } : {}
|
|
5865
5998
|
};
|
|
5999
|
+
if (asset.concept) {
|
|
6000
|
+
const image = await files.load(asset.concept, "Concept image");
|
|
6001
|
+
shape.concept = { path: import_node_path5.default.resolve(files.root, asset.concept), sha256: image.hash, width: image.width, height: image.height, format: image.format };
|
|
6002
|
+
}
|
|
5866
6003
|
if (asset.reference) {
|
|
5867
6004
|
const byDirection = typeof asset.reference === "string" ? { south: asset.reference } : asset.reference;
|
|
5868
6005
|
shape.reference = {};
|
|
@@ -7382,9 +7519,24 @@ var import_node_path11 = __toESM(require("path"), 1);
|
|
|
7382
7519
|
async function inspectRevisionReadiness(spec, lock) {
|
|
7383
7520
|
if (spec.mirror) return inspectMirror(spec, lock, /* @__PURE__ */ new Set());
|
|
7384
7521
|
if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
|
|
7522
|
+
if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
|
|
7385
7523
|
if (!spec.revision) return null;
|
|
7386
7524
|
return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
|
|
7387
7525
|
}
|
|
7526
|
+
async function inspectStyleAnchor(spec, lock, seen) {
|
|
7527
|
+
const anchor = spec.character.styleAnchor;
|
|
7528
|
+
const label = `style anchor ${spec.styleId}/${anchor.assetId}`;
|
|
7529
|
+
const dependency = await inspectParent(anchor.spec, lock, seen);
|
|
7530
|
+
if (!dependency.ready) return { ready: false, reason: `${label} is not ready: ${dependency.reason}` };
|
|
7531
|
+
if (!anchor.sha256 || !(0, import_node_fs8.existsSync)(anchor.file)) return { ready: false, reason: `${label} has no generated south-facing file yet` };
|
|
7532
|
+
if (await sha256File(anchor.file) !== anchor.sha256) {
|
|
7533
|
+
return { ready: false, reason: `${label} changed after the manifest was resolved` };
|
|
7534
|
+
}
|
|
7535
|
+
if (!lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)]?.objectId) {
|
|
7536
|
+
return { ready: false, reason: `${label} has no PixelLab character id recorded` };
|
|
7537
|
+
}
|
|
7538
|
+
return { ready: true, reason: `${label} is current` };
|
|
7539
|
+
}
|
|
7388
7540
|
async function inspectMirror(spec, lock, seen) {
|
|
7389
7541
|
const source = spec.mirror.sourceSpec;
|
|
7390
7542
|
const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
|
|
@@ -7456,6 +7608,10 @@ async function inspectParent(spec, lock, seen) {
|
|
|
7456
7608
|
const inputs = await inspectCharacterParent(spec, lock, nextSeen);
|
|
7457
7609
|
if (!inputs.ready) return inputs;
|
|
7458
7610
|
}
|
|
7611
|
+
if (spec.character?.styleAnchor) {
|
|
7612
|
+
const inputs = await inspectStyleAnchor(spec, lock, nextSeen);
|
|
7613
|
+
if (!inputs.ready) return inputs;
|
|
7614
|
+
}
|
|
7459
7615
|
if (spec.quality) {
|
|
7460
7616
|
const quality = await inspectQualityProfile(spec, lock);
|
|
7461
7617
|
return quality?.state === "approved" ? { ready: true, reason: "approved quality output is current" } : {
|
|
@@ -7495,6 +7651,14 @@ async function anyOutputModified(entry, spec) {
|
|
|
7495
7651
|
}
|
|
7496
7652
|
return false;
|
|
7497
7653
|
}
|
|
7654
|
+
function dependencies(spec) {
|
|
7655
|
+
return [
|
|
7656
|
+
spec.mirror?.sourceSpec,
|
|
7657
|
+
spec.revision?.sourceSpec,
|
|
7658
|
+
spec.character?.parentSpec,
|
|
7659
|
+
spec.character?.styleAnchor?.spec
|
|
7660
|
+
].filter((parent) => Boolean(parent));
|
|
7661
|
+
}
|
|
7498
7662
|
function resumeCommandForStatus(status) {
|
|
7499
7663
|
if (status === "pending" || status === "processing") return "poll";
|
|
7500
7664
|
if (status === "review") return "pick";
|
|
@@ -7603,16 +7767,19 @@ async function buildPlan(specs, lock, opts = {}) {
|
|
|
7603
7767
|
const stateOf = new Map(items.map((i) => [i.key, i.state]));
|
|
7604
7768
|
for (const item of items) {
|
|
7605
7769
|
if (!isActionable(item)) continue;
|
|
7606
|
-
const parent
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
item.
|
|
7615
|
-
|
|
7770
|
+
for (const parent of dependencies(item.spec)) {
|
|
7771
|
+
const parentKey = lockKey(parent.styleId, parent.assetId);
|
|
7772
|
+
const parentState = stateOf.get(parentKey);
|
|
7773
|
+
if (parentState && isActionable({ state: parentState })) {
|
|
7774
|
+
item.state = "blocked";
|
|
7775
|
+
item.reason = `parent ${parentKey} is being generated in this run; this follows in the next wave`;
|
|
7776
|
+
break;
|
|
7777
|
+
}
|
|
7778
|
+
if (item.spec.mirror && (parentState === "recoverable" || parentState === "in-flight")) {
|
|
7779
|
+
item.state = "blocked";
|
|
7780
|
+
item.reason = `mirror source ${parentKey} is ${parentState}; this follows in the next wave`;
|
|
7781
|
+
break;
|
|
7782
|
+
}
|
|
7616
7783
|
}
|
|
7617
7784
|
}
|
|
7618
7785
|
const actionable = items.filter(isActionable);
|
|
@@ -10091,10 +10258,13 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
|
|
|
10091
10258
|
try {
|
|
10092
10259
|
const refs = styleImages.get(spec.styleId) ?? [];
|
|
10093
10260
|
const parentEntry = spec.character?.parentSpec ? lock.entries[lockKey(spec.character.parentSpec.styleId, spec.character.parentSpec.assetId)] : void 0;
|
|
10261
|
+
const anchor = spec.character?.styleAnchor;
|
|
10262
|
+
const anchorEntry = anchor ? lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)] : void 0;
|
|
10094
10263
|
const replacedMetadata = previousEntry?.providerMetadata?.[provider.id];
|
|
10095
10264
|
const { jobId, metadata } = await provider.submit(spec, refs, {
|
|
10096
10265
|
...previousJobId ? { previousJobId } : {},
|
|
10097
10266
|
...parentEntry?.objectId ? { parentObjectId: parentEntry.objectId } : {},
|
|
10267
|
+
...anchorEntry?.objectId ? { styleObjectId: anchorEntry.objectId } : {},
|
|
10098
10268
|
...replacedMetadata ? { replacedMetadata } : {},
|
|
10099
10269
|
...previousMetadata ? { previousMetadata } : {},
|
|
10100
10270
|
checkpoint: async (checkpoint) => {
|
|
@@ -12703,7 +12873,7 @@ var pin_default = {
|
|
|
12703
12873
|
godot: "4.7.2",
|
|
12704
12874
|
extensionsApi: 9,
|
|
12705
12875
|
protocol: 4,
|
|
12706
|
-
release: "editor-pixelorama-v1.2.2-pk.
|
|
12876
|
+
release: "editor-pixelorama-v1.2.2-pk.26",
|
|
12707
12877
|
files: {
|
|
12708
12878
|
"index.apple-touch-icon.png": {
|
|
12709
12879
|
sha256: "ee5434873e0fed91e9a888c3ea5a8b79beac25999308be7a6eb41bf4ce640d27",
|
|
@@ -12718,7 +12888,7 @@ var pin_default = {
|
|
|
12718
12888
|
bytes: 7298
|
|
12719
12889
|
},
|
|
12720
12890
|
"index.html": {
|
|
12721
|
-
sha256: "
|
|
12891
|
+
sha256: "326101ab02bb4a29a7964214c9307c7dff26e9d66b8ebaaf6e7a3987e84a05b2",
|
|
12722
12892
|
bytes: 5442
|
|
12723
12893
|
},
|
|
12724
12894
|
"index.icon.png": {
|
|
@@ -12730,8 +12900,8 @@ var pin_default = {
|
|
|
12730
12900
|
bytes: 279815
|
|
12731
12901
|
},
|
|
12732
12902
|
"index.pck": {
|
|
12733
|
-
sha256: "
|
|
12734
|
-
bytes:
|
|
12903
|
+
sha256: "e26292650bb996965acd1ba70e74d2b4020b063d14f1276701312c1d34cb0a83",
|
|
12904
|
+
bytes: 6431932
|
|
12735
12905
|
},
|
|
12736
12906
|
"index.png": {
|
|
12737
12907
|
sha256: "6e3ca3eb4a99e4c07bdd89ebc873b440ec0ffd66ce1955160da9e7ed80d538d7",
|