pixelkiln 0.89.2 → 0.89.4
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/CONTRIBUTING.md +6 -0
- package/dist/cli.js +33 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +33 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +33 -5
- package/dist/index.js.map +1 -1
- package/docs/CHARACTERS.md +9 -0
- package/docs/ENDPOINTS.md +36 -2
- package/docs/GENERATORS.md +1 -1
- package/docs/PIXELLAB.md +6 -5
- package/package.json +1 -1
- package/skills/pixelkiln/references/pixellab-roadmap.md +6 -3
- package/skills/pixelkiln/references/pixellab.md +8 -3
package/dist/index.d.cts
CHANGED
|
@@ -21159,6 +21159,11 @@ interface SheetGroup {
|
|
|
21159
21159
|
height: number;
|
|
21160
21160
|
mode?: "candidates" | "frame-set";
|
|
21161
21161
|
frameLabels?: string[];
|
|
21162
|
+
/** Each frame's own size where it could be read (a locally cached PNG); null or absent, the sheet reads it off the loaded image. */
|
|
21163
|
+
frameSizes?: ({
|
|
21164
|
+
width: number;
|
|
21165
|
+
height: number;
|
|
21166
|
+
} | null)[];
|
|
21162
21167
|
fps?: number;
|
|
21163
21168
|
revision?: {
|
|
21164
21169
|
mode: RevisionMode;
|
package/dist/index.d.ts
CHANGED
|
@@ -21159,6 +21159,11 @@ interface SheetGroup {
|
|
|
21159
21159
|
height: number;
|
|
21160
21160
|
mode?: "candidates" | "frame-set";
|
|
21161
21161
|
frameLabels?: string[];
|
|
21162
|
+
/** Each frame's own size where it could be read (a locally cached PNG); null or absent, the sheet reads it off the loaded image. */
|
|
21163
|
+
frameSizes?: ({
|
|
21164
|
+
width: number;
|
|
21165
|
+
height: number;
|
|
21166
|
+
} | null)[];
|
|
21162
21167
|
fps?: number;
|
|
21163
21168
|
revision?: {
|
|
21164
21169
|
mode: RevisionMode;
|
package/dist/index.js
CHANGED
|
@@ -2056,7 +2056,8 @@ var PixelLabClient = class {
|
|
|
2056
2056
|
});
|
|
2057
2057
|
const text = await res.text();
|
|
2058
2058
|
if (!res.ok) {
|
|
2059
|
-
|
|
2059
|
+
const hint = res.status === 500 && text.includes("Failed to start any animation jobs") ? '; a skeleton-v3 loop needs a character with a stored 3D skeleton (a v3 base), use mode: "template" on a standard one' : "";
|
|
2060
|
+
throw new PixelLabError(`${init?.method ?? "GET"} ${path39} \u2192 ${res.status}${hint}`, res.status, text);
|
|
2060
2061
|
}
|
|
2061
2062
|
if (!text) return {};
|
|
2062
2063
|
try {
|
|
@@ -5682,6 +5683,11 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5682
5683
|
if (character.animation.mode !== "template" && character.animation.mode !== "skeleton-v3" && !spec.prompt.trim()) {
|
|
5683
5684
|
throw new Error(`${spec.styleId}/${spec.assetId} needs a prompt describing the motion, or a template`);
|
|
5684
5685
|
}
|
|
5686
|
+
if (character.animation.mode === "skeleton-v3" && character.mode === "standard") {
|
|
5687
|
+
throw new Error(
|
|
5688
|
+
`${spec.styleId}/${spec.assetId}: skeleton-v3 poses a template onto a 3D skeleton, which a ${character.mode} character has none of; use a v3 base (style mode: "v3"), or mode: "template" for this loop`
|
|
5689
|
+
);
|
|
5690
|
+
}
|
|
5685
5691
|
}
|
|
5686
5692
|
}
|
|
5687
5693
|
validateObjectPro(spec, styleImages = []) {
|
|
@@ -5988,7 +5994,10 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5988
5994
|
stateName: character.state_name ?? null,
|
|
5989
5995
|
directions: character.directions,
|
|
5990
5996
|
size: character.size,
|
|
5991
|
-
updatedAt: character.updated_at ?? null
|
|
5997
|
+
updatedAt: character.updated_at ?? null,
|
|
5998
|
+
// Kept: this metadata replaces the submit-time `character` entry,
|
|
5999
|
+
// and the job id is the only way to read the bill again later.
|
|
6000
|
+
...backgroundJobId ? { backgroundJobId } : {}
|
|
5992
6001
|
}
|
|
5993
6002
|
},
|
|
5994
6003
|
billed: await this.billedForJob(backgroundJobId)
|
|
@@ -6639,7 +6648,12 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
6639
6648
|
if (!backgroundJobId) return null;
|
|
6640
6649
|
try {
|
|
6641
6650
|
const job = await this.client.getBackgroundJob(backgroundJobId);
|
|
6642
|
-
|
|
6651
|
+
const nested = job.last_response?.billing_usage;
|
|
6652
|
+
for (const usage of [job.usage, nested]) {
|
|
6653
|
+
const billed = billedFromUsage(usage);
|
|
6654
|
+
if (billed && !(billed.unit === "usd" && billed.amount === 0)) return billed;
|
|
6655
|
+
}
|
|
6656
|
+
return null;
|
|
6643
6657
|
} catch {
|
|
6644
6658
|
return null;
|
|
6645
6659
|
}
|
|
@@ -16639,8 +16653,18 @@ GROUPS.forEach((g, gi) => {
|
|
|
16639
16653
|
preview.loading = 'lazy';
|
|
16640
16654
|
const index = document.createElement('span');
|
|
16641
16655
|
index.className = 'idx';
|
|
16642
|
-
|
|
16643
|
-
|
|
16656
|
+
// A frame's own size, not the manifest's: a 96px loop of a 64px
|
|
16657
|
+
// character is 96\xD796. Known up front for a cached file, else once loaded.
|
|
16658
|
+
const label = (w, h) => {
|
|
16659
|
+
index.textContent = (g.frameLabels?.[i] || String(i + 1)) + ' \xB7 ' + w + '\xD7' + h + ' \xB7 ' + scaleLabel;
|
|
16660
|
+
};
|
|
16661
|
+
const known = g.frameSizes?.[i];
|
|
16662
|
+
label(known ? known.width : g.width, known ? known.height : g.height);
|
|
16663
|
+
if (!known) {
|
|
16664
|
+
preview.addEventListener('load', () => {
|
|
16665
|
+
if (preview.naturalWidth && preview.naturalHeight) label(preview.naturalWidth, preview.naturalHeight);
|
|
16666
|
+
}, { once: true });
|
|
16667
|
+
}
|
|
16644
16668
|
c.append(preview, index);
|
|
16645
16669
|
if (g.recommendedIndex != null && i === recommended) {
|
|
16646
16670
|
const badge = document.createElement('span');
|
|
@@ -16902,12 +16926,15 @@ async function prepareReview(provider, lock, opts = {}) {
|
|
|
16902
16926
|
const urls = state.status === "review" ? state.candidateUrls : state.frameUrls;
|
|
16903
16927
|
const frameUrls = [];
|
|
16904
16928
|
const frameAssets = [];
|
|
16929
|
+
const frameSizes = [];
|
|
16905
16930
|
for (const [index, url] of urls.entries()) {
|
|
16906
16931
|
const cached = await cachedFrame(url);
|
|
16907
16932
|
if (!cached) {
|
|
16908
16933
|
frameUrls.push(url);
|
|
16934
|
+
frameSizes.push(null);
|
|
16909
16935
|
continue;
|
|
16910
16936
|
}
|
|
16937
|
+
frameSizes.push(cached.contentType === "image/png" ? pngSize(await readFile18(cached.path).catch(() => Buffer.alloc(0))) : null);
|
|
16911
16938
|
const route = `${prefix}/review-frame/${encodeURIComponent(String(groups.length))}/${index}`;
|
|
16912
16939
|
frameAssets.push([route, cached]);
|
|
16913
16940
|
frameUrls.push(route);
|
|
@@ -16933,6 +16960,7 @@ async function prepareReview(provider, lock, opts = {}) {
|
|
|
16933
16960
|
prompt: entry.prompt,
|
|
16934
16961
|
reviewObjectId: entry.reviewObjectId,
|
|
16935
16962
|
frameUrls,
|
|
16963
|
+
...frameSizes.some(Boolean) ? { frameSizes } : {},
|
|
16936
16964
|
width: entry.width,
|
|
16937
16965
|
height: entry.height,
|
|
16938
16966
|
...state.status === "review-set" ? {
|