pixelkiln 0.64.0 → 0.65.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.
@@ -57,18 +57,23 @@ Tiles and provider-native animation remain outside this contract.
57
57
 
58
58
  ## Dependency graph
59
59
 
60
- Four kinds of asset draw from another asset's generated bytes, and all four
60
+ Six kinds of asset draw from another asset's generated bytes, and all six
61
61
  are edges from a child spec to a parent spec in the same style: a
62
- `revision` (image-to-image or inpaint from a still), a character `state` or
63
- `animation` (drawn by PixelLab from the character it holds, so the edge is
64
- to the parent's south-facing file), a `mirror` (a local left-to-right flip
65
- of the parent's files), and a pro base's `styleCharacter` (the look it
66
- follows). Manifest loading rejects missing parents, self-references, and
67
- cycles. Resolution includes transitive parents even when `--only` selects
68
- just the child, chooses the parent's approved quality output when one
69
- exists, and hashes the parent's bytes (and a revision's optional mask) into
70
- the child identity, so a regenerated parent makes its children stale rather
71
- than silently mismatched.
62
+ `revision` (image-to-image or inpaint from a still), a character `state`,
63
+ `animation`, or `portrait` (drawn by PixelLab from the character it holds
64
+ or its south-facing file, so the edge is to that one file), a `mirror` (a
65
+ local left-to-right flip of the parent's files), an `outfit` (PixelLab
66
+ re-clothing a loop's whole frame set from a reference image, so the edge
67
+ is to every one of the parent's files, not one), and a pro base's
68
+ `styleCharacter` (the look it follows). Manifest loading rejects missing
69
+ parents, self-references, and cycles. Resolution includes transitive
70
+ parents even when `--only` selects just the child, chooses the parent's
71
+ approved quality output when one exists, and hashes the parent's bytes
72
+ (and a revision's optional mask) into the child identity for the
73
+ single-file edges, so a regenerated parent makes its children stale rather
74
+ than silently mismatched. A mirror and an outfit depend on the parent's
75
+ *whole* output set instead, tracked outside `specHash` (see below), since
76
+ there is no one file to hash at resolve time.
72
77
 
73
78
  Planning walks the graph from the child and reports `blocked` unless each
74
79
  parent is committed source, an intact current download, or a current approved
@@ -78,7 +83,10 @@ runs the plan in waves until nothing new becomes actionable. The submit
78
83
  boundary repeats the walk after queue and rate-limit waits, closing the gap
79
84
  between a printed plan and provider work. A mirror is the one edge with no
80
85
  provider on the far side: submit flips the files itself and records the
81
- parent's output hashes, and the plan compares those directly.
86
+ parent's output hashes, and the plan compares those directly. An outfit
87
+ records the same kind of hash over the parent's output set, but does call
88
+ a provider (`transfer-outfit-v2`) and costs generations; `billed` and the
89
+ usual lock lifecycle apply to it exactly as they do to a state or loop.
82
90
 
83
91
  Providers opt into revision modes through `supportsRevision`. The first
84
92
  implementation is ComfyUI: it uploads content-addressed inputs, binds only the
@@ -340,6 +340,67 @@ Engines that flip sprites at draw time (Godot's `flip_h`, Unity's
340
340
  you generate and flip in the engine; mirrors are for pipelines that want
341
341
  every direction on disk.
342
342
 
343
+ ## Portraits
344
+
345
+ A `portrait` asset is a bust made from a base or state's south sprite, and
346
+ attached to that character's own PixelLab record:
347
+
348
+ ```json
349
+ "mira.bust": { "portrait": { "of": "mira", "size": 64 } }
350
+ ```
351
+
352
+ `of` names the base or state to portray; `size` is one of PixelLab's fixed
353
+ result sizes (16, 32, 48, 64, 128, or 160 — 128 and 160 render at 2K and cost
354
+ more), independent of the style's own `size`. A portrait takes no prompt: it
355
+ is drawn from the parent's pixels, not text, so it is priced and generated
356
+ like a state, 20 to 40 generations by the size tier (a 16px portrait billed
357
+ exactly 20, the floor, in a live test; see [`docs/ENDPOINTS.md`](ENDPOINTS.md)).
358
+ It lands as `<asset>.png`, one file like a single-direction generator, and
359
+ `pixelkiln fetch` also attaches it to the parent's character record upstream
360
+ (a separate, free call PixelLab does not make on its own) — useful for
361
+ PixelLab's own tools, since the API otherwise has no way to read a
362
+ character's portrait back once set.
363
+
364
+ A portrait blocks until its parent is downloaded and current, and goes
365
+ `stale` when the parent is regenerated, exactly like a state. It takes no
366
+ `reference` or `concept` (those belong on a base) and no `state` or
367
+ `animation` (a portrait is not one of those, and the three are mutually
368
+ exclusive). Its view comes from the style, but only `low top-down`, `high
369
+ top-down`, or `side` are valid — narrower than a `standard` base's own
370
+ options, since the underlying endpoint takes a smaller set.
371
+
372
+ The reverse tool, drawing a full character from a portrait image, is not
373
+ implemented; see the open items in [`docs/ENDPOINTS.md`](ENDPOINTS.md).
374
+
375
+ ## Outfit transfer
376
+
377
+ An `outfit` asset re-clothes an existing loop's frames with a reference
378
+ outfit image, PixelLab's `transfer-outfit-v2`:
379
+
380
+ ```json
381
+ "mira.walk.armored": {
382
+ "outfit": { "of": "mira.walk", "reference": "refs/armor.png" }
383
+ }
384
+ ```
385
+
386
+ `of` names the loop (an `animation` asset) to re-clothe; `reference` is a
387
+ manifest-relative image of the outfit, 32 to 256px per side. An outfit takes
388
+ no prompt (drawn from pixels, not text) and reads its source loop's own
389
+ downloaded frames — 2 to 16 of them, PixelLab's own limit — rather than the
390
+ character record, so it works even once the source's PixelLab job record
391
+ has expired. It shares its source's width, height, and directions, and is
392
+ priced and generated like a state or loop, not for free like a `mirror`:
393
+ measured live at 20 generations for a 2-frame, 92×92 job (see
394
+ [`docs/ENDPOINTS.md`](ENDPOINTS.md)), the floor of the same tier a state
395
+ uses, not yet confirmed at other frame counts or canvases.
396
+
397
+ An outfit blocks until its source loop is downloaded and current — the
398
+ same rule a mirror's source follows, since both depend on a whole frame
399
+ set rather than one file — and goes `stale` when the source is
400
+ regenerated. It takes no `state`, `animation`, `portrait`, `reference`, or
401
+ `concept` (those describe a different shape or belong on a base); a
402
+ reference image change alone also makes it stale.
403
+
343
404
  ## Working with a cast
344
405
 
345
406
  - `pixelkiln plan` shows a state or loop as `blocked` until its parent is
package/docs/ENDPOINTS.md CHANGED
@@ -582,12 +582,11 @@ Listed so the gaps are known rather than assumed away:
582
582
  - `generate-font-pro`, job-based, with a response shape not in the simple
583
583
  `{usage, image}` form (wrapped by `pixelkiln font`, but its cost is not
584
584
  yet measured)
585
- - the character family beyond what the `character` generator uses: portraits
586
- (`portrait-character-pro` both ways, `/characters/{id}/portrait`), outfit
587
- transfer (`transfer-outfit-v2`), lip-sync, skeleton animation, and
588
- `source_image_id` on Pro Flash. The four creation engines, states, and
589
- `animate-character` are covered in full; see the September 2026 measurements
590
- below.
585
+ - the character family beyond what the `character` generator uses: lip-sync,
586
+ skeleton animation, `portrait_to_character` (a full character from a bust),
587
+ and `source_image_id` on Pro Flash. The four creation engines, states,
588
+ `animate-character`, portraits, and outfit transfer are covered in full; see
589
+ the September 2026 measurements below.
591
590
 
592
591
  ## Characters, measured
593
592
 
@@ -615,6 +614,27 @@ Listed so the gaps are known rather than assumed away:
615
614
  that is not a biped or one of the four quadrupeds, animate from text.
616
615
  - Request validation is strict: an unknown body field is a 422 listing every
617
616
  problem at once, which is a free way to check a body's shape.
617
+ - **`portrait-character-pro`** (`direction: character_to_portrait`, a full-body
618
+ sprite in, a bust out) is job-based: `POST` returns `background_job_id`,
619
+ `GET /portrait-character-pro/{job_id}` answers 423 while drawing and, once
620
+ `status: "completed"`, a `download_url` (its own `usage` is always `null`;
621
+ read the billed amount from `GET /background-jobs/{background_job_id}`
622
+ instead, same as every other job here). Not the couple-generations
623
+ "conversion" the name suggests: the smallest `result_size` (16px) billed
624
+ **20 generations**, the same order of magnitude as a state or `1dir`.
625
+ `POST /characters/{id}/portrait` (attaching a portrait image to a character
626
+ record) is a separate, synchronous, **free** call (`usage.generations: 0`);
627
+ its response is the only place the stored portrait's URL appears; the
628
+ character's own `GET /characters/{id}` never gains a portrait field, so
629
+ PixelKiln has to remember the URL itself. `character_to_portrait` and
630
+ `SetPortrait` are two independent calls with no automatic link between them.
631
+ - **`transfer-outfit-v2`** (a reference outfit image plus 2–16 existing
632
+ frames back wearing it) is job-based the same way, polled through
633
+ `GET /background-jobs/{id}` only (no dedicated status endpoint). A 2-frame,
634
+ 92×92 job billed **20 generations** — again a real generation cost, not a
635
+ cheap frame edit. The completed job returns the result frames inline as
636
+ base64 in `last_response.quantized_images`, not as storage URLs like every
637
+ other multi-frame result here.
618
638
 
619
639
  ---
620
640
 
@@ -221,12 +221,14 @@ system requests reduced motion and stops while it is offscreen. After approval,
221
221
 
222
222
  `character` is PixelLab's character family as managed assets: a base drawn
223
223
  facing 4 or 8 directions (from a prompt, or from your own south-facing
224
- sprite with `reference`), states (a pose, an outfit) that PixelLab applies
225
- to every direction of an existing character, and animations, one loop of
226
- one character in one direction. The three share one PixelLab character. A state
227
- or animation depends on its parent the way a revision does: the parent must
228
- be downloaded and current before the child can be submitted, and
229
- regenerating the parent makes the child stale.
224
+ sprite with `reference`), states (a pose or a text-edited outfit) that
225
+ PixelLab applies to every direction of an existing character, animations,
226
+ one loop of one character in one direction, portraits, a bust made from
227
+ the south sprite, and outfit transfers, an existing loop's frames
228
+ re-clothed from a reference image instead of text. A state, animation,
229
+ portrait, or outfit depends on its parent the way a revision does: the
230
+ parent must be downloaded and current before the child can be submitted,
231
+ and regenerating the parent makes the child stale.
230
232
 
231
233
  | Asset | PixelLab call | Cost |
232
234
  |---|---:|---:|
@@ -238,6 +240,8 @@ regenerating the parent makes the child stale.
238
240
  | animation with a `template` | animate-character | 1 |
239
241
  | animation from text (v3) | animate-character | ceil(size² × frames / 65536): 1 at 64px, 2 at 128px |
240
242
  | animation, `mode: pro` | animate-character | 20–40 by canvas |
243
+ | portrait | portrait-character-pro | 20–40 by `size` (16px billed exactly 20 live) |
244
+ | outfit | transfer-outfit-v2 | 20 (a 2-frame, 92×92 job billed exactly this live; not yet measured at other frame counts or canvases) |
241
245
 
242
246
  The 20–40 tiers are PixelLab's; the tier is resolved from the canvas when
243
247
  the job runs and reserved against the floor, so `plan` reports the tier the
package/docs/MANIFEST.md CHANGED
@@ -436,7 +436,9 @@ their own page: [Characters](./CHARACTERS.md) and
436
436
  "prompt": "walking in place, short legs stepping",
437
437
  "animation": { "of": "bot", "direction": "west", "frames": 12, "fps": 12 }
438
438
  },
439
- "bot.walk.east": { "mirror": "bot.walk.west" } // flipped locally, 0 generations
439
+ "bot.walk.east": { "mirror": "bot.walk.west" }, // flipped locally, 0 generations
440
+ "bot.bust": { "portrait": { "of": "bot", "size": 64 } }, // no prompt; drawn from bot's pixels
441
+ "bot.walk.west.armored": { "outfit": { "of": "bot.walk.west", "reference": "refs/armor.png" } }
440
442
  }
441
443
  }
442
444
  ```
package/docs/PIXELLAB.md CHANGED
@@ -156,10 +156,11 @@ comparing notes with someone using a different one:
156
156
 
157
157
  ## What is outside this adapter
158
158
 
159
- PixelLab offers more than PixelKiln currently exposes. Portraits, outfit
160
- transfer, lip-sync, and skeleton-driven animation are not part of this
161
- adapter. Characters, their states, and their animations are the `character`
162
- generator, with all four creation engines (standard, v3, pro, pro-flash),
159
+ PixelLab offers more than PixelKiln currently exposes. Lip-sync and
160
+ skeleton-driven animation are not part of this adapter. Characters, their
161
+ states, their animations, their portraits, and outfit transfer onto their
162
+ loops are the `character` generator, with all four creation engines
163
+ (standard, v3, pro, pro-flash),
163
164
  reference sprites, concept images, style anchors, mirrors, and every
164
165
  `animate-character` control; see [Characters](./CHARACTERS.md). Masked
165
166
  inpainting and whole-image editing are the `revision` asset shape, not the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelkiln",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "description": "Manifest-driven pixel-art generation, review, recovery, and packaging with deterministic provenance.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1388,6 +1388,53 @@
1388
1388
  },
1389
1389
  "minItems": 1
1390
1390
  },
1391
+ "portrait": {
1392
+ "type": "object",
1393
+ "properties": {
1394
+ "of": {
1395
+ "type": "string",
1396
+ "minLength": 1
1397
+ },
1398
+ "size": {
1399
+ "type": "number",
1400
+ "enum": [
1401
+ 16,
1402
+ 32,
1403
+ 48,
1404
+ 64,
1405
+ 128,
1406
+ 160
1407
+ ],
1408
+ "default": 64
1409
+ }
1410
+ },
1411
+ "required": [
1412
+ "of"
1413
+ ],
1414
+ "additionalProperties": false
1415
+ },
1416
+ "outfit": {
1417
+ "type": "object",
1418
+ "properties": {
1419
+ "of": {
1420
+ "type": "string",
1421
+ "minLength": 1
1422
+ },
1423
+ "reference": {
1424
+ "type": "string",
1425
+ "minLength": 1
1426
+ },
1427
+ "additionalInstructions": {
1428
+ "type": "string",
1429
+ "maxLength": 2000
1430
+ }
1431
+ },
1432
+ "required": [
1433
+ "of",
1434
+ "reference"
1435
+ ],
1436
+ "additionalProperties": false
1437
+ },
1391
1438
  "proportions": {
1392
1439
  "anyOf": [
1393
1440
  {
@@ -388,7 +388,8 @@ previously catalogued anywhere.
388
388
  `agent_inspect`/`agent_feedback`/`agent_help`) manage a *separate* PixelLab
389
389
  product — "deploy your own agent," confirmed directly from the live tool
390
390
  schemas — unrelated to game-asset generation. Nothing to build here.
391
- - Portraits, outfit transfer, and lip-sync/vocal-animation/talking-gif are
392
- already named as out of scope in docs/PIXELLAB.md. Portrait and
393
- outfit-transfer support exist on an internal branch stack not yet merged;
394
- lip-sync and vocal animation have no in-flight work.
391
+ - Lip-sync/vocal-animation/talking-gif are named as out of scope in
392
+ docs/PIXELLAB.md, with no in-flight work. Portraits (`portrait`) and outfit
393
+ transfer (`outfit`) are character asset kinds; see docs/CHARACTERS.md. They
394
+ were built and live-measured in September 2026 on a stacked branch that
395
+ never reached `main`, and were ported onto it later.