pixelkiln 0.85.0 → 0.86.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 CHANGED
@@ -777,6 +777,7 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
777
777
  revision: spec.revision ? {
778
778
  mode: spec.revision.mode,
779
779
  from: spec.revision.sourceAssetId,
780
+ fromStyle: spec.revision.sourceStyleId,
780
781
  sourceSha256: spec.revision.sourceSha256,
781
782
  maskSha256: spec.revision.maskSha256,
782
783
  strength: spec.revision.strength,
@@ -1126,8 +1127,16 @@ var RevisionDitheringSchema = z.enum(["none", "2x2", "4x4", "8x8"]);
1126
1127
  var RevisionSchema = z.object({
1127
1128
  /** What kind of controlled change the provider workflow performs. */
1128
1129
  mode: RevisionModeSchema,
1129
- /** Parent asset id in the same style. */
1130
+ /** Parent asset id. It lives in this asset's own style unless `fromStyle` names another. */
1130
1131
  from: z.string().min(1),
1132
+ /**
1133
+ * The style the parent lives in, when it is not this asset's own. The
1134
+ * parent is generated by that style's provider and model, and this
1135
+ * revision starts from its output file, so a chain (generate with one
1136
+ * model, clean up with another) is declared instead of restated by hand.
1137
+ * Styles may depend on one another but not in a cycle.
1138
+ */
1139
+ fromStyle: z.string().min(1).optional(),
1131
1140
  /** Manifest-relative black/white PNG. Required only for masked inpainting. */
1132
1141
  mask: z.string().min(1).optional(),
1133
1142
  /** Provider-neutral edit strength. The active adapter must bind it explicitly. */
@@ -1988,6 +1997,7 @@ var LockEntrySchema = z.object({
1988
1997
  revision: z.object({
1989
1998
  mode: RevisionModeSchema,
1990
1999
  sourceAssetId: z.string().min(1),
2000
+ sourceStyleId: z.string().min(1).optional(),
1991
2001
  sourceSha256: z.string().regex(/^[0-9a-f]{64}$/),
1992
2002
  maskSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),
1993
2003
  strength: z.number().min(0).max(1).optional(),
@@ -4405,7 +4415,7 @@ async function inspectRevision(spec, lock, seen) {
4405
4415
  if (!dependency.ready) {
4406
4416
  return {
4407
4417
  ready: false,
4408
- reason: `revision source ${spec.styleId}/${revision.sourceAssetId} is not ready: ${dependency.reason}`
4418
+ reason: `revision source ${revision.sourceStyleId ?? spec.styleId}/${revision.sourceAssetId} is not ready: ${dependency.reason}`
4409
4419
  };
4410
4420
  }
4411
4421
  if (revision.sourceMembers) {
@@ -10836,13 +10846,24 @@ ${issues}`);
10836
10846
  }
10837
10847
  }
10838
10848
  if (asset.revision) {
10839
- if (!parsed.data.assets[asset.revision.from]) {
10849
+ const parent = parsed.data.assets[asset.revision.from];
10850
+ if (!parent) {
10840
10851
  unknownReferences.push(
10841
10852
  `assets.${assetId}.revision.from: unknown asset "${asset.revision.from}"`
10842
10853
  );
10843
10854
  } else if (asset.revision.from === assetId) {
10844
10855
  unknownReferences.push(`assets.${assetId}.revision.from: an asset cannot revise itself`);
10845
10856
  }
10857
+ const fromStyle = asset.revision.fromStyle;
10858
+ if (fromStyle) {
10859
+ if (!styleIds.has(fromStyle)) {
10860
+ unknownReferences.push(`assets.${assetId}.revision.fromStyle: unknown style "${fromStyle}"`);
10861
+ } else if (parent && parent.styles.length && !parent.styles.includes(fromStyle)) {
10862
+ unknownReferences.push(
10863
+ `assets.${assetId}.revision.fromStyle: "${asset.revision.from}" is not in style "${fromStyle}"`
10864
+ );
10865
+ }
10866
+ }
10846
10867
  }
10847
10868
  for (const shape of ["state", "animation"]) {
10848
10869
  const of = asset[shape]?.of;
@@ -10958,7 +10979,7 @@ async function resolveSpecs(loaded, filter) {
10958
10979
  return provider;
10959
10980
  };
10960
10981
  const specs = [];
10961
- const styleIds = Object.keys(manifest.styles).filter(
10982
+ const requestedStyleIds = Object.keys(manifest.styles).filter(
10962
10983
  (id) => !filter?.styles?.length || filter.styles.includes(id)
10963
10984
  );
10964
10985
  for (const unknownStyle of filter?.styles ?? []) {
@@ -10983,6 +11004,39 @@ async function resolveSpecs(loaded, filter) {
10983
11004
  current = parentAssetId(manifest.assets[current]);
10984
11005
  }
10985
11006
  }
11007
+ const styleDependencies = /* @__PURE__ */ new Map();
11008
+ for (const styleId of Object.keys(manifest.styles)) {
11009
+ const needed = /* @__PURE__ */ new Set();
11010
+ for (const assetId of resolutionAssetIds) {
11011
+ const asset = manifest.assets[assetId];
11012
+ if (asset?.styles.length && !asset.styles.includes(styleId)) continue;
11013
+ const fromStyle = asset?.revision?.fromStyle;
11014
+ if (fromStyle && fromStyle !== styleId) needed.add(fromStyle);
11015
+ }
11016
+ styleDependencies.set(styleId, needed);
11017
+ }
11018
+ const styleIds = [];
11019
+ const emitStyles = new Set(requestedStyleIds);
11020
+ {
11021
+ const placed = /* @__PURE__ */ new Set();
11022
+ const visiting = [];
11023
+ const place = (styleId) => {
11024
+ if (placed.has(styleId)) return;
11025
+ const cycleStart = visiting.indexOf(styleId);
11026
+ if (cycleStart >= 0) {
11027
+ throw new Error(
11028
+ `Styles revise each other in a cycle: ${[...visiting.slice(cycleStart), styleId].join(" -> ")}. revision.fromStyle must form a chain, not a loop.`
11029
+ );
11030
+ }
11031
+ visiting.push(styleId);
11032
+ for (const dependency of styleDependencies.get(styleId) ?? []) place(dependency);
11033
+ visiting.pop();
11034
+ placed.add(styleId);
11035
+ styleIds.push(styleId);
11036
+ };
11037
+ for (const styleId of requestedStyleIds) place(styleId);
11038
+ }
11039
+ const styleFinalizers = /* @__PURE__ */ new Map();
10986
11040
  const styleImageCache = /* @__PURE__ */ new Map();
10987
11041
  async function loadStyleImage(rel, what = "Style image") {
10988
11042
  const abs = path14.resolve(root, rel);
@@ -11370,7 +11424,8 @@ async function resolveSpecs(loaded, filter) {
11370
11424
  `Provider "${activeProvider.id}" does not support ${asset.revision.mode} revisions`
11371
11425
  );
11372
11426
  }
11373
- const sourceSpec = await finalize(asset.revision.from);
11427
+ const sourceStyleId = asset.revision.fromStyle && asset.revision.fromStyle !== styleId ? asset.revision.fromStyle : void 0;
11428
+ const sourceSpec = sourceStyleId ? await styleFinalizers.get(sourceStyleId)(asset.revision.from) : await finalize(asset.revision.from);
11374
11429
  const sourceStem = sourceSpec.quality?.outFile ?? (sourceSpec.source ? path14.resolve(root, sourceSpec.source) : sourceSpec.outFile);
11375
11430
  const sourceMembers = await revisionSourceMembers(sourceStem, `revision source ${asset.revision.from}`);
11376
11431
  const sourceFile = sourceMembers?.[0]?.file ?? sourceStem;
@@ -11392,6 +11447,7 @@ async function resolveSpecs(loaded, filter) {
11392
11447
  resolved.revision = {
11393
11448
  mode: asset.revision.mode,
11394
11449
  sourceAssetId: asset.revision.from,
11450
+ ...sourceStyleId ? { sourceStyleId } : {},
11395
11451
  sourceFile,
11396
11452
  sourceSha256: sourceImage?.hash ?? null,
11397
11453
  sourceWidth: sourceImage?.width ?? null,
@@ -11513,6 +11569,8 @@ async function resolveSpecs(loaded, filter) {
11513
11569
  finalized.add(assetId);
11514
11570
  return resolved;
11515
11571
  };
11572
+ styleFinalizers.set(styleId, finalize);
11573
+ if (!emitStyles.has(styleId)) continue;
11516
11574
  for (const assetId of Object.keys(manifest.assets)) {
11517
11575
  if (!requestedAssetIds.has(assetId) || !styleSpecs.has(assetId)) continue;
11518
11576
  specs.push(await finalize(assetId));
@@ -15913,7 +15971,7 @@ async function buildGallerySnapshot(opts) {
15913
15971
  recordedSpecHash: entry?.specHash ?? null,
15914
15972
  currentSpecHash: spec.specHash,
15915
15973
  revision: entry?.revision ?? null,
15916
- revisionParentKey: spec.revision ? lockKey(spec.styleId, spec.revision.sourceAssetId) : entry?.revision ? lockKey(spec.styleId, entry.revision.sourceAssetId) : null,
15974
+ revisionParentKey: spec.revision ? lockKey(spec.revision.sourceStyleId ?? spec.styleId, spec.revision.sourceAssetId) : entry?.revision ? lockKey(entry.revision.sourceStyleId ?? spec.styleId, entry.revision.sourceAssetId) : null,
15917
15975
  mirrorOfKey: spec.mirror ? lockKey(spec.styleId, spec.mirror.sourceAssetId) : entry?.mirror ? lockKey(spec.styleId, entry.mirror.sourceAssetId) : null,
15918
15976
  skeleton: spec.revision?.mode === "animate-skeleton" && spec.revision.keypointsFile ? {
15919
15977
  keypointsFile: portableOutputPath(spec.revision.keypointsFile, root),
@@ -15983,7 +16041,7 @@ async function buildGallerySnapshot(opts) {
15983
16041
  recordedSpecHash: entry.specHash,
15984
16042
  currentSpecHash: null,
15985
16043
  revision: entry.revision,
15986
- revisionParentKey: entry.revision ? lockKey(entry.styleId, entry.revision.sourceAssetId) : null,
16044
+ revisionParentKey: entry.revision ? lockKey(entry.revision.sourceStyleId ?? entry.styleId, entry.revision.sourceAssetId) : null,
15987
16045
  mirrorOfKey: entry.mirror ? lockKey(entry.styleId, entry.mirror.sourceAssetId) : null,
15988
16046
  skeleton: null,
15989
16047
  character: describeCharacter(void 0, entry),
@@ -16919,6 +16977,7 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
16919
16977
  revision: spec.revision ? {
16920
16978
  mode: spec.revision.mode,
16921
16979
  sourceAssetId: spec.revision.sourceAssetId,
16980
+ ...spec.revision.sourceStyleId ? { sourceStyleId: spec.revision.sourceStyleId } : {},
16922
16981
  sourceSha256: spec.revision.sourceSha256,
16923
16982
  ...spec.revision.maskSha256 ? { maskSha256: spec.revision.maskSha256 } : {},
16924
16983
  ...spec.revision.strength == null ? {} : { strength: spec.revision.strength },