pixelkiln 0.89.3 → 0.89.5
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 +34 -5
- package/dist/cli.js.map +1 -1
- package/dist/client/gallery.js +30 -7
- package/dist/index.cjs +34 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +34 -5
- package/dist/index.js.map +1 -1
- package/docs/CHARACTERS.md +13 -1
- package/docs/ENDPOINTS.md +8 -0
- package/docs/PIXELLAB.md +2 -2
- package/package.json +1 -1
- package/skills/pixelkiln/references/pixellab.md +5 -1
package/CONTRIBUTING.md
CHANGED
|
@@ -42,6 +42,12 @@ npm run website:dev
|
|
|
42
42
|
The site reads canonical Markdown from `docs/` and the root policy files at
|
|
43
43
|
build time. Do not create a second documentation copy under `website/`.
|
|
44
44
|
|
|
45
|
+
The home page's "Latest updates from our providers" section reads
|
|
46
|
+
`website/app/lib/provider-updates.ts`. When a provider ships a feature
|
|
47
|
+
PixelKiln can use, add an entry at the top of that list. The newest entry
|
|
48
|
+
shows its figures and code sample; earlier ones collapse to a short row. Show
|
|
49
|
+
only output from a real call, with the bill the docs record.
|
|
50
|
+
|
|
45
51
|
Website sprites are generated from `website/art/pixelkiln.manifest.json`.
|
|
46
52
|
Treat those requests as paid work: run `plan` and `audit` first, use an explicit
|
|
47
53
|
hard budget, and commit the manifest, lockfile, and reviewed outputs together.
|
package/dist/cli.js
CHANGED
|
@@ -6704,7 +6704,8 @@ var PixelLabClient = class {
|
|
|
6704
6704
|
});
|
|
6705
6705
|
const text = await res.text();
|
|
6706
6706
|
if (!res.ok) {
|
|
6707
|
-
|
|
6707
|
+
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' : "";
|
|
6708
|
+
throw new PixelLabError(`${init?.method ?? "GET"} ${path53} \u2192 ${res.status}${hint}`, res.status, text);
|
|
6708
6709
|
}
|
|
6709
6710
|
if (!text) return {};
|
|
6710
6711
|
try {
|
|
@@ -9598,6 +9599,11 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
9598
9599
|
if (character.animation.mode !== "template" && character.animation.mode !== "skeleton-v3" && !spec.prompt.trim()) {
|
|
9599
9600
|
throw new Error(`${spec.styleId}/${spec.assetId} needs a prompt describing the motion, or a template`);
|
|
9600
9601
|
}
|
|
9602
|
+
if (character.animation.mode === "skeleton-v3" && character.mode === "standard") {
|
|
9603
|
+
throw new Error(
|
|
9604
|
+
`${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`
|
|
9605
|
+
);
|
|
9606
|
+
}
|
|
9601
9607
|
}
|
|
9602
9608
|
}
|
|
9603
9609
|
validateObjectPro(spec, styleImages = []) {
|
|
@@ -9904,7 +9910,10 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
9904
9910
|
stateName: character.state_name ?? null,
|
|
9905
9911
|
directions: character.directions,
|
|
9906
9912
|
size: character.size,
|
|
9907
|
-
updatedAt: character.updated_at ?? null
|
|
9913
|
+
updatedAt: character.updated_at ?? null,
|
|
9914
|
+
// Kept: this metadata replaces the submit-time `character` entry,
|
|
9915
|
+
// and the job id is the only way to read the bill again later.
|
|
9916
|
+
...backgroundJobId ? { backgroundJobId } : {}
|
|
9908
9917
|
}
|
|
9909
9918
|
},
|
|
9910
9919
|
billed: await this.billedForJob(backgroundJobId)
|
|
@@ -10555,7 +10564,12 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
10555
10564
|
if (!backgroundJobId) return null;
|
|
10556
10565
|
try {
|
|
10557
10566
|
const job = await this.client.getBackgroundJob(backgroundJobId);
|
|
10558
|
-
|
|
10567
|
+
const nested = job.last_response?.billing_usage;
|
|
10568
|
+
for (const usage of [job.usage, nested]) {
|
|
10569
|
+
const billed = billedFromUsage(usage);
|
|
10570
|
+
if (billed && !(billed.unit === "usd" && billed.amount === 0)) return billed;
|
|
10571
|
+
}
|
|
10572
|
+
return null;
|
|
10559
10573
|
} catch {
|
|
10560
10574
|
return null;
|
|
10561
10575
|
}
|
|
@@ -18024,6 +18038,7 @@ async function buildGallerySnapshot(opts) {
|
|
|
18024
18038
|
view: style?.view ?? null,
|
|
18025
18039
|
noBackground: style?.noBackground ?? true,
|
|
18026
18040
|
quality: Boolean(style?.quality),
|
|
18041
|
+
characterMode: style?.generator === "character" ? style.mode ?? "standard" : null,
|
|
18027
18042
|
characters: style?.generator === "character" || style?.generator === "objectPro" ? {
|
|
18028
18043
|
bases: styleItems.filter((item) => item.character?.kind === "base").length,
|
|
18029
18044
|
states: styleItems.filter((item) => item.character?.kind === "state").length,
|
|
@@ -19443,8 +19458,18 @@ GROUPS.forEach((g, gi) => {
|
|
|
19443
19458
|
preview.loading = 'lazy';
|
|
19444
19459
|
const index = document.createElement('span');
|
|
19445
19460
|
index.className = 'idx';
|
|
19446
|
-
|
|
19447
|
-
|
|
19461
|
+
// A frame's own size, not the manifest's: a 96px loop of a 64px
|
|
19462
|
+
// character is 96\xD796. Known up front for a cached file, else once loaded.
|
|
19463
|
+
const label = (w, h) => {
|
|
19464
|
+
index.textContent = (g.frameLabels?.[i] || String(i + 1)) + ' \xB7 ' + w + '\xD7' + h + ' \xB7 ' + scaleLabel;
|
|
19465
|
+
};
|
|
19466
|
+
const known = g.frameSizes?.[i];
|
|
19467
|
+
label(known ? known.width : g.width, known ? known.height : g.height);
|
|
19468
|
+
if (!known) {
|
|
19469
|
+
preview.addEventListener('load', () => {
|
|
19470
|
+
if (preview.naturalWidth && preview.naturalHeight) label(preview.naturalWidth, preview.naturalHeight);
|
|
19471
|
+
}, { once: true });
|
|
19472
|
+
}
|
|
19448
19473
|
c.append(preview, index);
|
|
19449
19474
|
if (g.recommendedIndex != null && i === recommended) {
|
|
19450
19475
|
const badge = document.createElement('span');
|
|
@@ -19625,12 +19650,15 @@ async function prepareReview(provider, lock, opts = {}) {
|
|
|
19625
19650
|
const urls = state.status === "review" ? state.candidateUrls : state.frameUrls;
|
|
19626
19651
|
const frameUrls = [];
|
|
19627
19652
|
const frameAssets = [];
|
|
19653
|
+
const frameSizes = [];
|
|
19628
19654
|
for (const [index, url] of urls.entries()) {
|
|
19629
19655
|
const cached = await cachedFrame(url);
|
|
19630
19656
|
if (!cached) {
|
|
19631
19657
|
frameUrls.push(url);
|
|
19658
|
+
frameSizes.push(null);
|
|
19632
19659
|
continue;
|
|
19633
19660
|
}
|
|
19661
|
+
frameSizes.push(cached.contentType === "image/png" ? pngSize(await readFile25(cached.path).catch(() => Buffer.alloc(0))) : null);
|
|
19634
19662
|
const route = `${prefix}/review-frame/${encodeURIComponent(String(groups.length))}/${index}`;
|
|
19635
19663
|
frameAssets.push([route, cached]);
|
|
19636
19664
|
frameUrls.push(route);
|
|
@@ -19656,6 +19684,7 @@ async function prepareReview(provider, lock, opts = {}) {
|
|
|
19656
19684
|
prompt: entry.prompt,
|
|
19657
19685
|
reviewObjectId: entry.reviewObjectId,
|
|
19658
19686
|
frameUrls,
|
|
19687
|
+
...frameSizes.some(Boolean) ? { frameSizes } : {},
|
|
19659
19688
|
width: entry.width,
|
|
19660
19689
|
height: entry.height,
|
|
19661
19690
|
...state.status === "review-set" ? {
|