pixelkiln 0.86.1 → 0.86.3

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/PROVIDERS.md CHANGED
@@ -27,7 +27,7 @@ them.
27
27
  | PixelLab | Production; paid generation and account workflows live-tested | `PIXELLAB_API_KEY` | generations |
28
28
  | Retro Diffusion | Experimental; authenticated paid still generation, download, provenance, and recovery live-tested; advanced workflows pending | `RD_API_KEY` | USD |
29
29
  | ComfyUI | Experimental; local generation, review, recovery, and image-to-image revision smoke live-tested on Apple MPS; inpaint/outpaint remain mock-tested | none; optional `COMFYUI_BASE_URL` | free |
30
- | Scenario | Experimental; BFL Flux 2 Dev authentication, CU preflight, paid single/two-output generation, review, download, and durable recovery live-tested | `SCENARIO_SDK_API_KEY` and `SCENARIO_SDK_API_SECRET` | compute-units |
30
+ | Scenario | Experimental; BFL Flux 2 Dev authentication, CU preflight, paid single/two-output generation, review, download, and durable recovery live-tested; reference-image edits, tool models, and multi-model chains run once each | `SCENARIO_SDK_API_KEY` and `SCENARIO_SDK_API_SECRET` | compute-units |
31
31
  | FakeProvider | Test-only deterministic lifecycle | none | free |
32
32
 
33
33
  Live tests now cover single-candidate RD Fast and RD Plus stills from cost quote
@@ -267,9 +267,11 @@ to ComfyUI. Provider-keyed budgets, independent orchestration, lock-authoritativ
267
267
  recovery, and explicit account-provider selection ship with it.
268
268
 
269
269
  The Scenario still-image adapter from
270
- [GitHub issue #52](https://github.com/gfargo/pixelkiln/issues/52) now has mocked
271
- edge coverage and a paid BFL Flux 2 Dev lifecycle smoke. It remains
272
- experimental until more model schemas and representative art briefs pass.
270
+ [GitHub issue #52](https://github.com/gfargo/pixelkiln/issues/52) has mocked edge
271
+ coverage, a paid BFL Flux 2 Dev lifecycle smoke, and a broader evaluation (ten
272
+ more models, six tool models, reference-image edits, multi-model chains, and a real
273
+ game's art) recorded in [Set up Scenario](./docs/SCENARIO.md#where-the-evidence-is).
274
+ It remains experimental until more model schemas and representative art briefs pass.
273
275
 
274
276
  | Candidate | What it adds | Fit with PixelKiln | Main cost or risk | Priority |
275
277
  |---|---|---|---|---:|
package/README.md CHANGED
@@ -366,7 +366,7 @@ verification. See [Library API](./docs/LIBRARY.md).
366
366
  | [Set up PixelLab](./docs/PIXELLAB.md) | Production-provider credentials, manifest, generators, and account workflows. |
367
367
  | [Set up Retro Diffusion](./docs/RETRO_DIFFUSION.md) | Experimental-provider credentials, styles, formats, cost checks, and limits. |
368
368
  | [Set up ComfyUI](./docs/COMFYUI.md) | Self-hosted stills, revisions, ordered frame sets, per-asset inputs, and quality limits. |
369
- | [Set up Scenario](./docs/SCENARIO.md) | Experimental hosted models, two-part credentials, CU preflight, review, and durable downloads. |
369
+ | [Set up Scenario](./docs/SCENARIO.md) | Experimental hosted models, two-part credentials, CU preflight, reference-image edits, multi-model chains, measured findings, and durable downloads. |
370
370
  | [Versioned recipes](./docs/RECIPES.md) | Pinned workflow packs, model hashes, manifest templates, and quality contracts. |
371
371
  | [Controlled revisions](./docs/REVISIONS.md) | Image-to-image, inpaint, palette cleanup, animation, and interpolation from a parent; masks, fail-closed readiness, provenance, and ComfyUI bindings. |
372
372
  | [CLI reference](./docs/CLI.md) | Every command, flag, JSON mode, and exit contract. |
package/dist/cli.js CHANGED
@@ -17650,6 +17650,12 @@ async function currentArt(entry, spec) {
17650
17650
  }
17651
17651
  return { path: file, contentType, width, height };
17652
17652
  }
17653
+ async function cachedFrame(url) {
17654
+ if (!url.startsWith("file://")) return null;
17655
+ const file = url.slice("file://".length);
17656
+ const contentType = mediaTypeFromExtension(file) ?? detectMediaType(await readFile23(file).catch(() => Buffer.alloc(0))) ?? "application/octet-stream";
17657
+ return { path: file, contentType };
17658
+ }
17653
17659
  async function prepareReview(provider, lock, opts = {}) {
17654
17660
  const log2 = opts.onProgress ?? (() => {
17655
17661
  });
@@ -17659,6 +17665,7 @@ async function prepareReview(provider, lock, opts = {}) {
17659
17665
  );
17660
17666
  const reviewAssets = /* @__PURE__ */ new Map();
17661
17667
  const prefix = opts.routePrefix ?? "";
17668
+ const providerUrls = /* @__PURE__ */ new Map();
17662
17669
  const groups = [];
17663
17670
  for (const [key, entry] of Object.entries(lock.entries)) {
17664
17671
  if (entry.provider !== provider.id || selectedKeys && !selectedKeys.has(key)) continue;
@@ -17667,7 +17674,19 @@ async function prepareReview(provider, lock, opts = {}) {
17667
17674
  const spec = specByKey.get(key);
17668
17675
  const state = await provider.poll(entry.reviewObjectId, entry.generator, { spec, metadata: entry.providerMetadata?.[provider.id] });
17669
17676
  if (state.status !== "review" && state.status !== "review-set" || (state.status === "review" ? !state.candidateUrls.length : !state.frameUrls.length)) continue;
17670
- const frameUrls = state.status === "review" ? state.candidateUrls : state.frameUrls;
17677
+ const urls = state.status === "review" ? state.candidateUrls : state.frameUrls;
17678
+ const frameUrls = [];
17679
+ const frameAssets = [];
17680
+ for (const [index, url] of urls.entries()) {
17681
+ const cached = await cachedFrame(url);
17682
+ if (!cached) {
17683
+ frameUrls.push(url);
17684
+ continue;
17685
+ }
17686
+ const route = `${prefix}/review-frame/${encodeURIComponent(String(groups.length))}/${index}`;
17687
+ frameAssets.push([route, cached]);
17688
+ frameUrls.push(route);
17689
+ }
17671
17690
  const sourceRoute = spec?.revision ? `${prefix}/revision-source/${encodeURIComponent(String(groups.length))}` : null;
17672
17691
  if (sourceRoute && spec?.revision) {
17673
17692
  reviewAssets.set(sourceRoute, {
@@ -17680,6 +17699,8 @@ async function prepareReview(provider, lock, opts = {}) {
17680
17699
  if (current && currentRoute) {
17681
17700
  reviewAssets.set(currentRoute, { path: current.path, contentType: current.contentType });
17682
17701
  }
17702
+ for (const [route, asset] of frameAssets) reviewAssets.set(route, asset);
17703
+ providerUrls.set(key, urls);
17683
17704
  groups.push({
17684
17705
  key,
17685
17706
  assetId: entry.assetId,
@@ -17762,7 +17783,7 @@ async function prepareReview(provider, lock, opts = {}) {
17762
17783
  status: "selected",
17763
17784
  objectId,
17764
17785
  candidateIndex: index,
17765
- sourceUrl: sourceUrl ?? group.frameUrls[index] ?? null,
17786
+ sourceUrl: sourceUrl ?? providerUrls.get(key)?.[index] ?? null,
17766
17787
  sourceUrls: [],
17767
17788
  provider: provider.id,
17768
17789
  providerMetadata: metadata ? {