pixelkiln 0.45.0 → 0.46.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +92 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +92 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +522 -72
- package/dist/index.d.ts +522 -72
- package/dist/index.js +92 -18
- package/dist/index.js.map +1 -1
- package/docs/GENERATORS.md +1 -0
- package/docs/MANIFEST.md +21 -12
- package/package.json +1 -1
- package/schema/manifest.schema.json +40 -2
- package/schema/recipe.schema.json +20 -1
- package/skills/pixelkiln/references/pixellab.md +1 -1
package/dist/cli.js
CHANGED
|
@@ -676,6 +676,7 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
676
676
|
textGuidanceScale: spec.character.textGuidanceScale,
|
|
677
677
|
isometric: spec.character.isometric,
|
|
678
678
|
enhancePrompt: spec.character.enhancePrompt,
|
|
679
|
+
styleTraits: spec.character.styleTraits,
|
|
679
680
|
reference: spec.character.reference ? Object.fromEntries(Object.entries(spec.character.reference).map(([direction, image]) => [direction, image.sha256])) : void 0,
|
|
680
681
|
concept: spec.character.concept?.sha256,
|
|
681
682
|
styleAnchor: spec.character.styleAnchor ? { of: spec.character.styleAnchor.assetId, sha256: spec.character.styleAnchor.sha256 } : void 0
|
|
@@ -795,7 +796,7 @@ var MIRRORED_DIRECTION = {
|
|
|
795
796
|
west: "east",
|
|
796
797
|
"south-west": "south-east"
|
|
797
798
|
};
|
|
798
|
-
var CharacterModeSchema = z.enum(["standard", "v3", "pro"]);
|
|
799
|
+
var CharacterModeSchema = z.enum(["standard", "v3", "pro", "pro-flash"]);
|
|
799
800
|
var CHARACTER_PROPORTION_PRESETS = ["default", "chibi", "cartoon", "stylized", "realistic_male", "realistic_female", "heroic"];
|
|
800
801
|
var CharacterProportionsSchema = z.union([
|
|
801
802
|
z.enum(CHARACTER_PROPORTION_PRESETS),
|
|
@@ -991,14 +992,27 @@ var StyleObjectSchema = z.object({
|
|
|
991
992
|
/**
|
|
992
993
|
* `character` only. `standard` draws from a skeleton template for 1
|
|
993
994
|
* generation; `v3` is the highest quality at 2 to 9 by size; `pro` is a
|
|
994
|
-
* reference-based engine at 20 to 40 by size
|
|
995
|
-
*
|
|
995
|
+
* reference-based engine at 20 to 40 by size; `pro-flash` draws a
|
|
996
|
+
* south sprite with PixelLab's newest image model and rotates it with
|
|
997
|
+
* v3, 6 to 17 by size, or the rotations alone (1 at 64px) from a
|
|
998
|
+
* `reference`. States inherit the parent's engine; animations choose
|
|
999
|
+
* their own.
|
|
996
1000
|
*/
|
|
997
1001
|
mode: CharacterModeSchema.optional(),
|
|
998
|
-
/** `character` only. Rotations per base or state.
|
|
1002
|
+
/** `character` only. Rotations per base or state. Every engine but `standard` draws 8. */
|
|
999
1003
|
directions: z.union([z.literal(4), z.literal(8)]).optional(),
|
|
1000
|
-
/** `character` only. Body template: `mannequin` (default)
|
|
1004
|
+
/** `character` only. Body template: `mannequin` (default), a quadruped (`bear`, `cat`, `dog`, `horse`, `lion`), or `custom` for `pro-flash`. */
|
|
1001
1005
|
template: z.string().min(1).optional(),
|
|
1006
|
+
/**
|
|
1007
|
+
* `character` only, `pro-flash` bases with a style image: which traits
|
|
1008
|
+
* the style image lends. Each defaults to true.
|
|
1009
|
+
*/
|
|
1010
|
+
styleTraits: z.object({
|
|
1011
|
+
palette: z.boolean().optional(),
|
|
1012
|
+
outline: z.boolean().optional(),
|
|
1013
|
+
detail: z.boolean().optional(),
|
|
1014
|
+
shading: z.boolean().optional()
|
|
1015
|
+
}).strict().optional(),
|
|
1002
1016
|
/** `character` only, `standard` humanoid bases. A preset or multipliers; an asset may override it. */
|
|
1003
1017
|
proportions: CharacterProportionsSchema.optional(),
|
|
1004
1018
|
/**
|
|
@@ -5442,6 +5456,29 @@ var PixelLabClient = class {
|
|
|
5442
5456
|
...south ? { reference_image: encode(south) } : {},
|
|
5443
5457
|
...args.enhancePrompt ? { enhance_prompt: true } : {}
|
|
5444
5458
|
};
|
|
5459
|
+
} else if (args.mode === "pro-flash") {
|
|
5460
|
+
path45 = "/create-character-pro-flash";
|
|
5461
|
+
const traits = args.styleTraits;
|
|
5462
|
+
body = {
|
|
5463
|
+
description: args.description,
|
|
5464
|
+
template_id: args.template,
|
|
5465
|
+
n_directions: 8,
|
|
5466
|
+
// The author's sprite sets the canvas; a size only applies to text creation.
|
|
5467
|
+
...south ? { first_frame: encode(south) } : { image_size: imageSize },
|
|
5468
|
+
...args.view ? { view: args.view } : {},
|
|
5469
|
+
...args.seed != null ? { seed: args.seed } : {},
|
|
5470
|
+
...args.styleReference && args.styleReferenceSize ? {
|
|
5471
|
+
style_image: { image: encode(args.styleReference), size: args.styleReferenceSize },
|
|
5472
|
+
...traits ? {
|
|
5473
|
+
style_options: {
|
|
5474
|
+
...traits.palette !== void 0 ? { color_palette: traits.palette } : {},
|
|
5475
|
+
...traits.outline !== void 0 ? { outline: traits.outline } : {},
|
|
5476
|
+
...traits.detail !== void 0 ? { detail: traits.detail } : {},
|
|
5477
|
+
...traits.shading !== void 0 ? { shading: traits.shading } : {}
|
|
5478
|
+
}
|
|
5479
|
+
} : {}
|
|
5480
|
+
} : {}
|
|
5481
|
+
};
|
|
5445
5482
|
} else if (args.mode === "pro") {
|
|
5446
5483
|
path45 = "/create-character-pro";
|
|
5447
5484
|
body = {
|
|
@@ -5619,12 +5656,24 @@ function characterCost(spec) {
|
|
|
5619
5656
|
if (character.kind === "state") return generationCost(spec.width, spec.height, "1dir");
|
|
5620
5657
|
if (character.mode === "standard") return 1;
|
|
5621
5658
|
if (character.mode === "v3") return 1 + Math.max(1, Math.ceil(px * 8 / 65536));
|
|
5659
|
+
if (character.mode === "pro-flash") {
|
|
5660
|
+
const south = character.reference?.south;
|
|
5661
|
+
return south ? proFlashCharacterCost(south.width, south.height, true) : proFlashCharacterCost(spec.width, spec.height, false);
|
|
5662
|
+
}
|
|
5622
5663
|
return generationCost(spec.width, spec.height, "1dir");
|
|
5623
5664
|
}
|
|
5665
|
+
function proFlashCharacterCost(width, height, fromReference) {
|
|
5666
|
+
const side = Math.max(32, Math.ceil(Math.max(width, height) / 4) * 4);
|
|
5667
|
+
const rotations = Math.max(1, Math.ceil(side * side * 8 / 65536));
|
|
5668
|
+
if (fromReference) return rotations;
|
|
5669
|
+
const image = side <= 96 ? 5 : side <= 208 ? 6 : 9;
|
|
5670
|
+
return image + rotations;
|
|
5671
|
+
}
|
|
5624
5672
|
function characterAnimationName(spec) {
|
|
5625
5673
|
return `pixelkiln:${spec.styleId}/${spec.assetId}`;
|
|
5626
5674
|
}
|
|
5627
5675
|
var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
|
|
5676
|
+
var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
|
|
5628
5677
|
function encodeAnimationJob(job) {
|
|
5629
5678
|
return `character-animation:${Buffer.from(JSON.stringify(job)).toString("base64url")}`;
|
|
5630
5679
|
}
|
|
@@ -5783,7 +5832,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5783
5832
|
if (!character.reference.south) throw new Error(`${label}: a reference needs a south-facing sprite`);
|
|
5784
5833
|
if (character.mode !== "standard") {
|
|
5785
5834
|
if (given.length > 1) throw new Error(`${label}: PixelLab ${character.mode} rotates one south-facing reference; drop the other directions`);
|
|
5786
|
-
const limit = character.mode === "
|
|
5835
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
5787
5836
|
const south = character.reference.south;
|
|
5788
5837
|
if (south.width > limit || south.height > limit) {
|
|
5789
5838
|
throw new Error(`${label}: reference is ${south.width}x${south.height}; PixelLab ${character.mode} takes up to ${limit}px`);
|
|
@@ -5807,26 +5856,39 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5807
5856
|
}
|
|
5808
5857
|
}
|
|
5809
5858
|
if (styleImages.length) {
|
|
5810
|
-
if (character.mode !== "pro") {
|
|
5859
|
+
if (character.mode !== "pro" && character.mode !== "pro-flash") {
|
|
5811
5860
|
throw new Error(
|
|
5812
|
-
`PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro for a style anchor`
|
|
5861
|
+
`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`
|
|
5813
5862
|
);
|
|
5814
5863
|
}
|
|
5815
|
-
if (styleImages.length > 1) throw new Error(
|
|
5864
|
+
if (styleImages.length > 1) throw new Error(`PixelLab ${character.mode} characters take one style image`);
|
|
5816
5865
|
if (character.kind === "base" && character.reference) {
|
|
5817
|
-
throw new Error(`${label}: a
|
|
5866
|
+
throw new Error(`${label}: a ${character.mode} base rotating its own reference takes no style image`);
|
|
5818
5867
|
}
|
|
5819
5868
|
const image = styleImages[0];
|
|
5820
|
-
|
|
5821
|
-
|
|
5869
|
+
const limit = character.mode === "pro" ? 168 : 256;
|
|
5870
|
+
if (image.width > limit || image.height > limit) {
|
|
5871
|
+
throw new Error(`PixelLab ${character.mode} character style image is ${image.width}x${image.height}; the limit is ${limit}px`);
|
|
5872
|
+
}
|
|
5873
|
+
if (character.mode === "pro-flash" && (image.width > spec.width || image.height > spec.height)) {
|
|
5874
|
+
throw new Error(
|
|
5875
|
+
`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`
|
|
5876
|
+
);
|
|
5822
5877
|
}
|
|
5823
5878
|
}
|
|
5824
|
-
|
|
5879
|
+
if (character.styleTraits && character.mode !== "pro-flash") {
|
|
5880
|
+
throw new Error(`${label}: styleTraits choose what a pro-flash style image lends; the ${character.mode} engine does not take them`);
|
|
5881
|
+
}
|
|
5882
|
+
const maxSize = character.mode === "v3" || character.mode === "pro-flash" ? 256 : 128;
|
|
5825
5883
|
if (spec.width < 16 || spec.height < 16 || spec.width > maxSize || spec.height > maxSize) {
|
|
5826
5884
|
throw new Error(`PixelLab ${character.mode} characters must be between 16 and ${maxSize} pixels`);
|
|
5827
5885
|
}
|
|
5828
|
-
if (
|
|
5829
|
-
throw new Error(`PixelLab
|
|
5886
|
+
if (character.mode === "pro-flash" && character.kind === "base" && (spec.width % 4 || spec.height % 4)) {
|
|
5887
|
+
throw new Error(`PixelLab pro-flash characters are sized in multiples of 4 pixels; ${spec.width}x${spec.height} is not`);
|
|
5888
|
+
}
|
|
5889
|
+
const templates = character.mode === "pro-flash" ? PRO_FLASH_TEMPLATES : CHARACTER_TEMPLATES;
|
|
5890
|
+
if (!templates.includes(character.template)) {
|
|
5891
|
+
throw new Error(`PixelLab ${character.mode} character template must be one of: ${templates.join(", ")}`);
|
|
5830
5892
|
}
|
|
5831
5893
|
const views = character.mode === "standard" ? ["low top-down", "high top-down", "side", "perspective", "oblique"] : ["low top-down", "high top-down", "side"];
|
|
5832
5894
|
if (!views.includes(spec.view)) {
|
|
@@ -5881,7 +5943,9 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5881
5943
|
styleReference: styleImage ? { base64: styleImage.base64, format: styleImage.format } : void 0,
|
|
5882
5944
|
enhancePrompt: character.enhancePrompt,
|
|
5883
5945
|
concept: character.concept ? readPose(spec, "concept image", character.concept) : void 0,
|
|
5884
|
-
styleCharacterId: character.styleAnchor ? requireStyleObjectId(spec, context) : void 0
|
|
5946
|
+
styleCharacterId: character.styleAnchor ? requireStyleObjectId(spec, context) : void 0,
|
|
5947
|
+
styleReferenceSize: styleImage ? { width: styleImage.width, height: styleImage.height } : void 0,
|
|
5948
|
+
styleTraits: character.styleTraits
|
|
5885
5949
|
});
|
|
5886
5950
|
return { jobId: res2.character_id, metadata: { character: { kind: "base", characterId: res2.character_id, mode: character.mode, directions: character.directions, backgroundJobId: res2.background_job_id } } };
|
|
5887
5951
|
}
|
|
@@ -7789,7 +7853,8 @@ async function resolveCharacterShape(asset, style, kind, files) {
|
|
|
7789
7853
|
...proportions !== void 0 ? { proportions } : {},
|
|
7790
7854
|
...style.textGuidanceScale !== void 0 ? { textGuidanceScale: style.textGuidanceScale } : {},
|
|
7791
7855
|
...style.isometric !== void 0 ? { isometric: style.isometric } : {},
|
|
7792
|
-
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {}
|
|
7856
|
+
...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {},
|
|
7857
|
+
...style.styleTraits ? { styleTraits: style.styleTraits } : {}
|
|
7793
7858
|
};
|
|
7794
7859
|
if (asset.concept) {
|
|
7795
7860
|
const image = await files.load(asset.concept, "Concept image");
|
|
@@ -8023,8 +8088,9 @@ async function fetchAssets(provider, specs, lock, lockPath, opts = {}) {
|
|
|
8023
8088
|
const superseded = (entry.supersededOutputs ?? []).find(
|
|
8024
8089
|
(output, oldIndex, all) => currentOutputPath(output, spec, oldIndex, all.length) === target
|
|
8025
8090
|
);
|
|
8091
|
+
const outgoing = Boolean(superseded && currentHash === superseded.sha256);
|
|
8026
8092
|
if (!opts.force) {
|
|
8027
|
-
if (
|
|
8093
|
+
if (outgoing) {
|
|
8028
8094
|
} else if (recorded || superseded) {
|
|
8029
8095
|
throw new Error(
|
|
8030
8096
|
`refusing to overwrite modified output ${target}; pass --force to replace it`
|
|
@@ -8035,6 +8101,14 @@ async function fetchAssets(provider, specs, lock, lockPath, opts = {}) {
|
|
|
8035
8101
|
);
|
|
8036
8102
|
}
|
|
8037
8103
|
}
|
|
8104
|
+
if (outgoing && cacheDir) {
|
|
8105
|
+
try {
|
|
8106
|
+
const oldBytes = await readFile7(target);
|
|
8107
|
+
const oldMediaType = detectMediaType(oldBytes);
|
|
8108
|
+
if (oldMediaType) await cacheMedia(cacheDir, oldBytes, oldMediaType, currentHash);
|
|
8109
|
+
} catch {
|
|
8110
|
+
}
|
|
8111
|
+
}
|
|
8038
8112
|
log2(
|
|
8039
8113
|
` replace ${path14.relative(process.cwd(), target)}` + (opts.force ? " (--force)" : " (previous tracked generation)")
|
|
8040
8114
|
);
|