pixelkiln 0.40.0 → 0.41.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 +102 -7
- package/dist/cli.js.map +1 -1
- package/dist/client/gallery.css +1 -0
- package/dist/client/gallery.js +39 -0
- package/dist/index.cjs +114 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +114 -7
- package/dist/index.js.map +1 -1
- package/docs/CLI.md +11 -6
- package/docs/ENDPOINTS.md +7 -0
- package/docs/GENERATORS.md +4 -1
- package/docs/PIXELLAB.md +7 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5448,12 +5448,7 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5448
5448
|
const character = await this.client.getCharacter(jobId);
|
|
5449
5449
|
if (character.status === "failed") return { status: "failed", error: "character generation failed upstream" };
|
|
5450
5450
|
if (character.status !== "completed" || !character.rotation_urls) return { status: "processing" };
|
|
5451
|
-
const
|
|
5452
|
-
const sources = [];
|
|
5453
|
-
for (const direction of order) {
|
|
5454
|
-
const url = character.rotation_urls[direction];
|
|
5455
|
-
if (url) sources.push({ url, role: direction });
|
|
5456
|
-
}
|
|
5451
|
+
const sources = rotationSources(character);
|
|
5457
5452
|
if (!sources.length) return { status: "failed", error: "character completed with no rotation images" };
|
|
5458
5453
|
return {
|
|
5459
5454
|
status: "ready",
|
|
@@ -5745,6 +5740,27 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
5745
5740
|
})))
|
|
5746
5741
|
};
|
|
5747
5742
|
}
|
|
5743
|
+
/**
|
|
5744
|
+
* A character's rotation and frame URLs carry its last edit time as a
|
|
5745
|
+
* cache-buster, so the record's URLs can name bytes a cache still holds
|
|
5746
|
+
* after an edit in PixelLab's editor. Objects keep stable URLs.
|
|
5747
|
+
*/
|
|
5748
|
+
async refreshSources(objectId, context) {
|
|
5749
|
+
if (context.generator !== "character") return void 0;
|
|
5750
|
+
const [characterId, groupId] = objectId.split("#");
|
|
5751
|
+
const character = await this.client.getCharacter(characterId).catch((err) => {
|
|
5752
|
+
if (err instanceof PixelLabError && err.status === 404) return null;
|
|
5753
|
+
throw err;
|
|
5754
|
+
});
|
|
5755
|
+
if (!character) return null;
|
|
5756
|
+
if (!groupId) return character.status === "completed" ? rotationSources(character) : void 0;
|
|
5757
|
+
const recorded = context.metadata?.character ?? {};
|
|
5758
|
+
const direction = recorded.direction ?? "south";
|
|
5759
|
+
const group = character.animations.find((g) => g.animation_group_id === groupId);
|
|
5760
|
+
const frames = group?.directions.find((d) => d.direction === direction && d.frames.length)?.frames ?? (recorded.animationName ? findAnimation(character, recorded.animationName, direction, recorded.animationId ?? null)?.frames : void 0);
|
|
5761
|
+
if (!frames) return null;
|
|
5762
|
+
return frames.map((url, index) => ({ url, role: `frame-${String(index).padStart(2, "0")}` }));
|
|
5763
|
+
}
|
|
5748
5764
|
};
|
|
5749
5765
|
function remoteCharacter(character) {
|
|
5750
5766
|
return {
|
|
@@ -5775,6 +5791,15 @@ function firstUrl(urls) {
|
|
|
5775
5791
|
if (!urls) return null;
|
|
5776
5792
|
return Object.values(urls).find((u) => typeof u === "string") ?? null;
|
|
5777
5793
|
}
|
|
5794
|
+
function rotationSources(character) {
|
|
5795
|
+
const order = character.directions === 4 ? CHARACTER_DIRECTIONS_4 : CHARACTER_DIRECTIONS_8;
|
|
5796
|
+
const sources = [];
|
|
5797
|
+
for (const direction of order) {
|
|
5798
|
+
const url = character.rotation_urls?.[direction];
|
|
5799
|
+
if (url) sources.push({ url, role: direction });
|
|
5800
|
+
}
|
|
5801
|
+
return sources;
|
|
5802
|
+
}
|
|
5778
5803
|
function findAnimation(character, name, direction, animationId) {
|
|
5779
5804
|
for (const group of character.animations) {
|
|
5780
5805
|
const match = group.directions.find((d) => d.direction === direction && d.frames.length > 0);
|
|
@@ -7331,7 +7356,40 @@ async function fetchAssets(provider, specs, lock, lockPath, opts = {}) {
|
|
|
7331
7356
|
result.skipped++;
|
|
7332
7357
|
continue;
|
|
7333
7358
|
}
|
|
7334
|
-
const
|
|
7359
|
+
const recordedSources = entry.sourceUrls?.length ? entry.sourceUrls : entry.sourceUrl ? [{ url: entry.sourceUrl }] : opts.repair && entry.outputs.length ? entry.outputs.map((o) => ({ url: "", role: o.role, mediaType: o.mediaType })) : [];
|
|
7360
|
+
let sources = recordedSources;
|
|
7361
|
+
let rotated = false;
|
|
7362
|
+
if (opts.refresh && entry.status === "downloaded" && entry.objectId && provider.refreshSources) {
|
|
7363
|
+
let current;
|
|
7364
|
+
try {
|
|
7365
|
+
current = await provider.refreshSources(entry.objectId, {
|
|
7366
|
+
generator: entry.generator,
|
|
7367
|
+
metadata: entry.providerMetadata?.[provider.id],
|
|
7368
|
+
sources: recordedSources
|
|
7369
|
+
});
|
|
7370
|
+
} catch (err) {
|
|
7371
|
+
const message6 = err instanceof Error ? err.message : String(err);
|
|
7372
|
+
upsert(lock, key, { status: "download-failed", error: `download failed: ${message6}` });
|
|
7373
|
+
result.failed++;
|
|
7374
|
+
log2(` FAILED ${key}: ${message6}`);
|
|
7375
|
+
await saveLock(lockPath, lock);
|
|
7376
|
+
continue;
|
|
7377
|
+
}
|
|
7378
|
+
if (current === null) {
|
|
7379
|
+
upsert(lock, key, { status: "download-failed", error: `download failed: ${entry.objectId} no longer exists upstream` });
|
|
7380
|
+
result.failed++;
|
|
7381
|
+
log2(` FAILED ${key}: ${entry.objectId} no longer exists upstream`);
|
|
7382
|
+
await saveLock(lockPath, lock);
|
|
7383
|
+
continue;
|
|
7384
|
+
}
|
|
7385
|
+
if (current) {
|
|
7386
|
+
sources = current.map((source) => ({
|
|
7387
|
+
...source,
|
|
7388
|
+
mediaType: source.mediaType ?? recordedSources.find((r) => r.role === source.role)?.mediaType
|
|
7389
|
+
}));
|
|
7390
|
+
rotated = sources.length !== recordedSources.length || sources.some((source, index) => source.url !== recordedSources[index]?.url || source.role !== recordedSources[index]?.role);
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7335
7393
|
if (!sources.length) {
|
|
7336
7394
|
upsert(lock, key, {
|
|
7337
7395
|
status: "download-failed",
|
|
@@ -7460,6 +7518,10 @@ async function fetchAssets(provider, specs, lock, lockPath, opts = {}) {
|
|
|
7460
7518
|
log2(` wrote ${path13.relative(process.cwd(), target)}`);
|
|
7461
7519
|
}
|
|
7462
7520
|
if (opts.refresh && !wrote) {
|
|
7521
|
+
if (rotated) {
|
|
7522
|
+
const persistent = sources.filter((source) => shouldPersistSourceUrl(source.url));
|
|
7523
|
+
upsert(lock, key, { sourceUrl: persistent[0]?.url ?? null, sourceUrls: persistent });
|
|
7524
|
+
}
|
|
7463
7525
|
result.unchanged = (result.unchanged ?? 0) + 1;
|
|
7464
7526
|
continue;
|
|
7465
7527
|
}
|
|
@@ -10177,6 +10239,32 @@ async function samePixels(a, b) {
|
|
|
10177
10239
|
}
|
|
10178
10240
|
}
|
|
10179
10241
|
var metadataFps = (entry) => entry ? frameSetFps(entry) : null;
|
|
10242
|
+
function describeCharacter(spec, entry) {
|
|
10243
|
+
const recorded = entry?.providerMetadata?.[entry.provider]?.character;
|
|
10244
|
+
if (spec?.character) {
|
|
10245
|
+
const character = spec.character;
|
|
10246
|
+
return {
|
|
10247
|
+
kind: character.kind,
|
|
10248
|
+
parentKey: character.parentAssetId ? lockKey(spec.styleId, character.parentAssetId) : null,
|
|
10249
|
+
mode: character.kind === "animation" ? character.animation.mode : character.mode,
|
|
10250
|
+
directions: character.directions,
|
|
10251
|
+
direction: character.animation?.direction ?? null,
|
|
10252
|
+
characterId: recorded?.characterId ?? entry?.objectId?.split("#")[0] ?? null
|
|
10253
|
+
};
|
|
10254
|
+
}
|
|
10255
|
+
if (entry?.generator === "character") {
|
|
10256
|
+
const kind = recorded?.kind === "animation" || entry.outputs.some((o) => o.role?.startsWith("frame-")) ? "animation" : "base";
|
|
10257
|
+
return {
|
|
10258
|
+
kind,
|
|
10259
|
+
parentKey: null,
|
|
10260
|
+
mode: recorded?.mode ?? "standard",
|
|
10261
|
+
directions: recorded?.directions ?? entry.outputs.length,
|
|
10262
|
+
direction: recorded?.direction ?? null,
|
|
10263
|
+
characterId: recorded?.characterId ?? entry.objectId?.split("#")[0] ?? null
|
|
10264
|
+
};
|
|
10265
|
+
}
|
|
10266
|
+
return null;
|
|
10267
|
+
}
|
|
10180
10268
|
async function fileInfo(absolutePath) {
|
|
10181
10269
|
try {
|
|
10182
10270
|
const info = await stat2(absolutePath);
|
|
@@ -10385,6 +10473,7 @@ async function buildGallerySnapshot(opts) {
|
|
|
10385
10473
|
currentSpecHash: spec.specHash,
|
|
10386
10474
|
revision: entry?.revision ?? null,
|
|
10387
10475
|
revisionParentKey: spec.revision ? lockKey(spec.styleId, spec.revision.sourceAssetId) : entry?.revision ? lockKey(spec.styleId, entry.revision.sourceAssetId) : null,
|
|
10476
|
+
character: describeCharacter(spec, entry),
|
|
10388
10477
|
outputs,
|
|
10389
10478
|
quality,
|
|
10390
10479
|
providerMetadata: entry?.providerMetadata ?? {},
|
|
@@ -10446,6 +10535,7 @@ async function buildGallerySnapshot(opts) {
|
|
|
10446
10535
|
currentSpecHash: null,
|
|
10447
10536
|
revision: entry.revision,
|
|
10448
10537
|
revisionParentKey: entry.revision ? lockKey(entry.styleId, entry.revision.sourceAssetId) : null,
|
|
10538
|
+
character: describeCharacter(void 0, entry),
|
|
10449
10539
|
outputs,
|
|
10450
10540
|
quality: null,
|
|
10451
10541
|
providerMetadata: entry.providerMetadata ?? {},
|
|
@@ -10502,6 +10592,11 @@ async function buildGallerySnapshot(opts) {
|
|
|
10502
10592
|
view: style?.view ?? null,
|
|
10503
10593
|
noBackground: style?.noBackground ?? true,
|
|
10504
10594
|
quality: Boolean(style?.quality),
|
|
10595
|
+
characters: style?.generator === "character" ? {
|
|
10596
|
+
bases: styleItems.filter((item) => item.character?.kind === "base").length,
|
|
10597
|
+
states: styleItems.filter((item) => item.character?.kind === "state").length,
|
|
10598
|
+
animations: styleItems.filter((item) => item.character?.kind === "animation").length
|
|
10599
|
+
} : null,
|
|
10505
10600
|
tags: style?.tags ?? [],
|
|
10506
10601
|
extends: typeof rawStyle?.extends === "string" ? rawStyle.extends : null,
|
|
10507
10602
|
ownFields: rawStyle ? Object.keys(rawStyle).filter((key) => key !== "extends") : [],
|