pixelkiln 0.59.0 → 0.60.1

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/index.cjs CHANGED
@@ -97,6 +97,8 @@ __export(index_exports, {
97
97
  ScenarioProvider: () => ScenarioProvider,
98
98
  StyleInputSchema: () => StyleInputSchema,
99
99
  StyleSchema: () => StyleSchema,
100
+ UiElementSchema: () => UiElementSchema,
101
+ UiPieceSchema: () => UiPieceSchema,
100
102
  UnsupportedCapabilityError: () => UnsupportedCapabilityError,
101
103
  UsageError: () => UsageError,
102
104
  WorkspaceProjectSchema: () => WorkspaceProjectSchema,
@@ -306,7 +308,7 @@ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
306
308
  // src/types.ts
307
309
  var import_zod = require("zod");
308
310
  var MediaTypeSchema = import_zod.z.enum(["image/png", "image/gif"]);
309
- var GeneratorSchema = import_zod.z.enum(["1dir", "map", "pixflux", "tiles", "animation", "frames", "character", "terrain", "imagePro", "isometricTile", "objectPro"]);
311
+ var GeneratorSchema = import_zod.z.enum(["1dir", "map", "pixflux", "tiles", "animation", "frames", "character", "terrain", "imagePro", "isometricTile", "objectPro", "uiAsset"]);
310
312
  var GridConfidenceSchema = import_zod.z.enum(["low", "medium", "high"]);
311
313
  var RevisionModeSchema = import_zod.z.enum([
312
314
  "image-to-image",
@@ -428,6 +430,50 @@ var CharacterProportionsSchema = import_zod.z.union([
428
430
  }).strict()
429
431
  ]);
430
432
  var CharacterAnimationModeSchema = import_zod.z.enum(["template", "v3", "pro"]);
433
+ var UiPieceSchema = import_zod.z.discriminatedUnion("kind", [
434
+ import_zod.z.object({
435
+ id: import_zod.z.string().min(1),
436
+ kind: import_zod.z.literal("rounded_rect"),
437
+ label: import_zod.z.string().optional(),
438
+ x: import_zod.z.number(),
439
+ y: import_zod.z.number(),
440
+ w: import_zod.z.number(),
441
+ h: import_zod.z.number(),
442
+ radius: import_zod.z.number().min(0).optional()
443
+ }).strict(),
444
+ import_zod.z.object({
445
+ id: import_zod.z.string().min(1),
446
+ kind: import_zod.z.literal("circle"),
447
+ label: import_zod.z.string().optional(),
448
+ x: import_zod.z.number(),
449
+ y: import_zod.z.number(),
450
+ r: import_zod.z.number()
451
+ }).strict(),
452
+ import_zod.z.object({
453
+ id: import_zod.z.string().min(1),
454
+ kind: import_zod.z.literal("polygon"),
455
+ label: import_zod.z.string().optional(),
456
+ x: import_zod.z.number(),
457
+ y: import_zod.z.number(),
458
+ r: import_zod.z.number(),
459
+ sides: import_zod.z.number().int().min(3),
460
+ phase: import_zod.z.number().optional()
461
+ }).strict()
462
+ ]);
463
+ var UiElementSchema = import_zod.z.enum([
464
+ "button",
465
+ "icon_button",
466
+ "toolbar",
467
+ "tab",
468
+ "panel",
469
+ "window",
470
+ "health_bar",
471
+ "avatar",
472
+ "triangle",
473
+ "pentagon",
474
+ "hexagon",
475
+ "octagon"
476
+ ]);
431
477
  var AssetBatchSchema = import_zod.z.object({
432
478
  /** The batch leader: another `1dir` asset in the same style. */
433
479
  of: import_zod.z.string().min(1),
@@ -730,6 +776,12 @@ var StyleObjectSchema = import_zod.z.object({
730
776
  * in place of `terrainShapeStyle`. The API default is `standard`.
731
777
  */
732
778
  terrainMode: import_zod.z.enum(["standard", "pro"]).optional(),
779
+ /**
780
+ * `uiAsset` generator only. A natural-language palette hint sent as-is
781
+ * (e.g. "brown and gold"), distinct from `palette`'s hex-color array —
782
+ * this is a prompt-level steer, not a local quantization target.
783
+ */
784
+ uiColorPalette: import_zod.z.string().max(200).optional(),
733
785
  /**
734
786
  * `terrain` generator only, `terrainMode: "standard"`. Procedural
735
787
  * boundary geometry: `square` or `round`, 16px or 32px tiles only.
@@ -1013,6 +1065,10 @@ var AssetSchema = import_zod.z.object({
1013
1065
  * `AssetBatchSchema`.
1014
1066
  */
1015
1067
  batch: AssetBatchSchema.optional(),
1068
+ /** `uiAsset` styles: precise shape regions the panel is composited from. Combine with `elements`; omit both for a default full-canvas panel. */
1069
+ pieces: import_zod.z.array(UiPieceSchema).min(1).optional(),
1070
+ /** `uiAsset` styles: named, auto-positioned UI element scaffolds. Combine with `pieces`; omit both for a default full-canvas panel. */
1071
+ elements: import_zod.z.array(UiElementSchema).min(1).optional(),
1016
1072
  /** `character` styles, `standard` humanoid bases: this character's proportions, over the style's. */
1017
1073
  proportions: CharacterProportionsSchema.optional(),
1018
1074
  /**
@@ -1530,6 +1586,19 @@ var IsometricTileGetSchema = import_zod2.z.object({
1530
1586
  image: import_zod2.z.object({ base64: import_zod2.z.string().min(1), format: import_zod2.z.string().default("png") }).passthrough(),
1531
1587
  usage: UsageSchema
1532
1588
  }).passthrough();
1589
+ var UiAssetSubmitSchema = import_zod2.z.object({
1590
+ ui_asset_id: import_zod2.z.string().min(1),
1591
+ background_job_id: import_zod2.z.string().min(1),
1592
+ status: import_zod2.z.string().default("processing"),
1593
+ usage: UsageSchema
1594
+ }).passthrough();
1595
+ var UiAssetGetSchema = import_zod2.z.object({
1596
+ id: import_zod2.z.string().min(1),
1597
+ status: import_zod2.z.string().nullable().default(null),
1598
+ image_url: import_zod2.z.string().nullable().optional(),
1599
+ progress_percent: import_zod2.z.number().nullable().optional(),
1600
+ eta_seconds: import_zod2.z.number().nullable().optional()
1601
+ }).passthrough();
1533
1602
  var RevisionJobSubmitSchema = import_zod2.z.object({
1534
1603
  background_job_id: import_zod2.z.string().min(1),
1535
1604
  status: import_zod2.z.string().default("processing")
@@ -1890,6 +1959,48 @@ var PixelLabClient = class {
1890
1959
  );
1891
1960
  return { image: res.image, usage: res.usage ?? null };
1892
1961
  }
1962
+ /**
1963
+ * `/create-ui-asset`: one composited panel image from a shape template —
1964
+ * `pieces` (precise rect/circle/polygon regions on a virtual 0–512
1965
+ * editor canvas) and/or named `elements` (auto-positioned scaffolds:
1966
+ * button, icon_button, toolbar, tab, panel, window, health_bar, avatar,
1967
+ * triangle, pentagon, hexagon, octagon), or neither for a default
1968
+ * full-canvas rounded-rect panel. Unlike every other generator here, the
1969
+ * result is one flat image with no per-piece sub-regions or nine-slice
1970
+ * metadata returned — cropping a `pieces` layout into separate files
1971
+ * would be pixelkiln's own local work, not modeled yet.
1972
+ */
1973
+ async createUiAsset(args) {
1974
+ const body = {
1975
+ description: args.description,
1976
+ image_size: { width: args.width, height: args.height }
1977
+ };
1978
+ if (args.pieces?.length) body.pieces = args.pieces;
1979
+ if (args.elements?.length) body.elements = args.elements;
1980
+ if (args.styleImage) body.style_image = args.styleImage;
1981
+ if (args.colorPalette) body.color_palette = args.colorPalette;
1982
+ if (args.noBackground != null) body.no_background = args.noBackground;
1983
+ if (args.seed != null) body.seed = args.seed;
1984
+ const res = await validateResponse(
1985
+ UiAssetSubmitSchema,
1986
+ await this.request("/create-ui-asset", { method: "POST", body: JSON.stringify(body) }),
1987
+ "create ui asset"
1988
+ );
1989
+ return { ui_asset_id: res.ui_asset_id, background_job_id: res.background_job_id, usage: res.usage };
1990
+ }
1991
+ async getUiAsset(uiAssetId) {
1992
+ const res = await validateResponse(
1993
+ UiAssetGetSchema,
1994
+ await this.request(`/ui-assets/${encodeURIComponent(uiAssetId)}`),
1995
+ "get ui asset"
1996
+ );
1997
+ return {
1998
+ status: res.status,
1999
+ imageUrl: res.image_url ?? null,
2000
+ progressPercent: res.progress_percent ?? null,
2001
+ etaSeconds: res.eta_seconds ?? null
2002
+ };
2003
+ }
1893
2004
  /**
1894
2005
  * Synchronous single-image generation. Returns the PNG inline rather than a
1895
2006
  * job id, and is the only endpoint that honours a forced palette;
@@ -3027,16 +3138,20 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
3027
3138
  detail: spec.detail ?? null,
3028
3139
  seed: spec.seed ?? null,
3029
3140
  palette: spec.palette,
3030
- // `noBackground` only reaches the wire for pixflux; the tile fields are
3031
- // undefined for every other generator. `tileSize` is intentionally
3032
- // absent; width/height are derived from it, so it is already covered.
3033
- noBackground: spec.generator === "pixflux" || spec.provider !== "pixellab" ? spec.noBackground : void 0,
3141
+ // `noBackground` only reaches the wire for pixflux and uiAsset; the
3142
+ // tile fields are undefined for every other generator. `tileSize` is
3143
+ // intentionally absent; width/height are derived from it, so it is
3144
+ // already covered.
3145
+ noBackground: spec.generator === "pixflux" || spec.generator === "uiAsset" || spec.provider !== "pixellab" ? spec.noBackground : void 0,
3034
3146
  tileType: spec.tileType,
3035
3147
  tileView: spec.tileView,
3036
3148
  tileFeature: spec.tileFeature,
3037
3149
  outlineMode: spec.outlineMode,
3038
3150
  isometricTileSize: spec.isometricTileSize,
3039
3151
  isometricTileShape: spec.isometricTileShape,
3152
+ uiPieces: spec.uiPieces,
3153
+ uiElements: spec.uiElements,
3154
+ uiColorPalette: spec.uiColorPalette,
3040
3155
  styleImages: styleImageHashes,
3041
3156
  // A character family: the engine and rotations of a base, the parent's
3042
3157
  // generated bytes for a state or animation (so a regenerated parent
@@ -3234,7 +3349,7 @@ var PixelLabProvider = class _PixelLabProvider {
3234
3349
  return new _PixelLabProvider(new PixelLabClient("download-only"));
3235
3350
  }
3236
3351
  supports(generator) {
3237
- return generator === "1dir" || generator === "map" || generator === "pixflux" || generator === "tiles" || generator === "terrain" || generator === "imagePro" || generator === "character" || generator === "isometricTile" || generator === "objectPro";
3352
+ return generator === "1dir" || generator === "map" || generator === "pixflux" || generator === "tiles" || generator === "terrain" || generator === "imagePro" || generator === "character" || generator === "isometricTile" || generator === "objectPro" || generator === "uiAsset";
3238
3353
  }
3239
3354
  /**
3240
3355
  * `inpaint` (`/inpaint-v3`, a mask) and `image-to-image` (`/edit-images-v2`,
@@ -3350,6 +3465,11 @@ var PixelLabProvider = class _PixelLabProvider {
3350
3465
  `PixelLab imagePro is ${spec.width}x${spec.height}; the API takes 16 to 792 wide and 16 to 688 tall (the exact ceiling also depends on aspect ratio)`
3351
3466
  );
3352
3467
  }
3468
+ if (spec.generator === "uiAsset" && (spec.width < 192 || spec.height < 192 || spec.width > 688 || spec.height > 688)) {
3469
+ throw new Error(
3470
+ `PixelLab uiAsset is ${spec.width}x${spec.height}; the API takes 192 to 688 pixels per side (the exact ceiling also depends on aspect ratio \u2014 square tops out at 512, 16:9 at 688x384, 9:16 at 384x688, 4:3 at 600x448, 3:4 at 448x600)`
3471
+ );
3472
+ }
3353
3473
  if (spec.generator === "map") {
3354
3474
  requirePixelLabOption("map", "view", spec.view, ["low top-down", "high top-down", "side"]);
3355
3475
  requirePixelLabOption("map", "outline", spec.outline, [
@@ -3987,6 +4107,20 @@ var PixelLabProvider = class _PixelLabProvider {
3987
4107
  if (spec.revision) return this.submitRevision(spec);
3988
4108
  if (spec.generator === "character") return this.submitCharacter(spec, styleImages, context);
3989
4109
  if (spec.generator === "objectPro") return this.submitObjectPro(spec, styleImages, context);
4110
+ if (spec.generator === "uiAsset") {
4111
+ const res2 = await this.client.createUiAsset({
4112
+ description: spec.prompt,
4113
+ width: spec.width,
4114
+ height: spec.height,
4115
+ pieces: spec.uiPieces,
4116
+ elements: spec.uiElements,
4117
+ styleImage: styleImages[0] ? { base64: styleImages[0].base64, format: styleImages[0].format } : void 0,
4118
+ colorPalette: spec.uiColorPalette,
4119
+ noBackground: spec.noBackground,
4120
+ seed: spec.seed
4121
+ });
4122
+ return { jobId: res2.ui_asset_id, metadata: { backgroundJobId: res2.background_job_id } };
4123
+ }
3990
4124
  if (spec.generator === "pixflux") {
3991
4125
  const swatch = spec.palette.length ? paletteSwatch(spec.palette).toString("base64") : void 0;
3992
4126
  const { png } = await this.client.createImagePixflux({
@@ -4263,6 +4397,7 @@ var PixelLabProvider = class _PixelLabProvider {
4263
4397
  if (generator === "imagePro") return this.pollImagePro(jobId);
4264
4398
  if (generator === "character") return this.pollCharacter(jobId, context);
4265
4399
  if (generator === "objectPro") return this.pollObjectPro(jobId, context);
4400
+ if (generator === "uiAsset") return this.pollUiAsset(jobId, context);
4266
4401
  const backgroundJobId = context?.metadata?.backgroundJobId;
4267
4402
  const obj = await this.client.getObject(jobId);
4268
4403
  if (obj.status === "review") {
@@ -4582,6 +4717,29 @@ var PixelLabProvider = class _PixelLabProvider {
4582
4717
  throw err;
4583
4718
  }
4584
4719
  }
4720
+ /**
4721
+ * `/ui-assets/{id}` reports progress with its own `status` field
4722
+ * ("processing"/"completed"/"failed") rather than a 423, and its result is
4723
+ * one flat composited image at a hosted `image_url` — no per-piece
4724
+ * sub-images, no nine-slice metadata, confirmed absent from the response
4725
+ * schema. There is nothing to review: one job is one ready image, like
4726
+ * `isometricTile`.
4727
+ */
4728
+ async pollUiAsset(uiAssetId, context) {
4729
+ const asset = await this.client.getUiAsset(uiAssetId);
4730
+ if (asset.status === "failed") return { status: "failed", error: "UI asset generation failed upstream" };
4731
+ if (asset.status !== "completed" || !asset.imageUrl) {
4732
+ return { status: "processing", progressPercent: asset.progressPercent, etaSeconds: asset.etaSeconds };
4733
+ }
4734
+ const backgroundJobId = context?.metadata?.backgroundJobId;
4735
+ return {
4736
+ status: "ready",
4737
+ objectId: uiAssetId,
4738
+ sourceUrl: asset.imageUrl,
4739
+ sources: [{ url: asset.imageUrl }],
4740
+ billed: await this.billedForJob(backgroundJobId)
4741
+ };
4742
+ }
4585
4743
  async selectCandidate(jobId, index, commonTag, generator) {
4586
4744
  if (generator === "tiles") {
4587
4745
  const set = await this.client.getTilesPro(jobId);
@@ -7362,6 +7520,10 @@ async function resolveSpecs(loaded, filter) {
7362
7520
  size = asset.size ?? style.size ?? 64;
7363
7521
  width = size;
7364
7522
  height = size;
7523
+ } else if (generator === "uiAsset") {
7524
+ width = asset.width ?? style.size ?? 256;
7525
+ height = asset.height ?? style.size ?? 256;
7526
+ size = Math.max(width, height);
7365
7527
  } else {
7366
7528
  width = asset.width ?? style.size ?? 64;
7367
7529
  height = asset.height ?? style.size ?? 64;
@@ -7372,6 +7534,11 @@ async function resolveSpecs(loaded, filter) {
7372
7534
  `assets.${assetId}: ${asset.state ? "state" : "animation"} needs a character or objectPro style; "${styleId}" generates ${generator}`
7373
7535
  );
7374
7536
  }
7537
+ if ((asset.pieces || asset.elements) && generator !== "uiAsset") {
7538
+ throw new Error(
7539
+ `assets.${assetId}: ${asset.pieces ? "pieces" : "elements"} needs a uiAsset style; "${styleId}" generates ${generator}`
7540
+ );
7541
+ }
7375
7542
  const characterKind = asset.animation ? "animation" : asset.state ? "state" : "base";
7376
7543
  const subject = asset.promptByStyle[styleId] ?? asset.prompt ?? "";
7377
7544
  let terrainLowerDescription;
@@ -7418,6 +7585,9 @@ async function resolveSpecs(loaded, filter) {
7418
7585
  shading: style.shading,
7419
7586
  detail: style.detail,
7420
7587
  seed: style.seed,
7588
+ uiPieces: generator === "uiAsset" ? asset.pieces : void 0,
7589
+ uiElements: generator === "uiAsset" ? asset.elements : void 0,
7590
+ uiColorPalette: generator === "uiAsset" ? style.uiColorPalette : void 0,
7421
7591
  palette: style.palette,
7422
7592
  enforcePalette: style.enforcePalette,
7423
7593
  noBackground: style.noBackground,
@@ -16529,6 +16699,8 @@ async function workspaceStatus(ws, dir) {
16529
16699
  ScenarioProvider,
16530
16700
  StyleInputSchema,
16531
16701
  StyleSchema,
16702
+ UiElementSchema,
16703
+ UiPieceSchema,
16532
16704
  UnsupportedCapabilityError,
16533
16705
  UsageError,
16534
16706
  WorkspaceProjectSchema,