Enhance on demand: ComfyUI templates, jobs, approve as version (#192) #196

Merged
cameron merged 3 commits from feat/192-enhance into master 2026-10-30 19:41:43 +00:00
Owner

What

Enhance on demand (#192): run a ComfyUI restore/edit template on a photo from the apps, preview it through ImageApi, approve it in-app, and it lands as a photo version (#191).

  • enhance.toml (annotated enhance.example.toml, gitignored, no secrets): templates, path map, timings. A template missing imageapi:source / imageapi:save, or with a prompt node lacking text|prompt|value, is logged and skipped; the rest load. Stray SaveImage nodes are a startup warning.
  • Template fill: nodes found by _meta.title; require_approval forced; prompt append (per-template prompt_join, default one space) or replace (required, empty is a 400); reference node and every link to it removed when no reference_path; fresh value for every seed, noise_seed and *.seed input per submit.
  • Path map /media/nas/ <-> Z:\ (longest prefix, both directions).
  • enhance_jobs table plus a background poller (/queue then /history/{id}): queued, running, ready, failed, and expired when ComfyUI forgot the prompt (restart). unavailable after unreachable_grace_secs.
  • Idle POST /free once per quiet spell (empty queue, no active job, newest /history unchanged for idle_free_secs; measured on ImageApi's clock).
  • Approve calls /imageapi/approve, maps the returned path, runs a targeted ingest (watcher::register_new_files, extracted from process_new_files, plus versions::link_new_files), and answers with the version. Idempotent.
  • ImageApi never writes under library roots; ComfyUI is never exposed to the apps.

API shapes are documented in CLAUDE.md ("Enhance on demand") and match FileViewer-React#57 as specified.

Differences from the ticket text (FileViewer please note)

  • GET /enhance/templates returns an object {available, reason?, default, warn_above_megapixels, templates: [...]}, not a bare array. Extra per-template fields: prompt_required, default, output_megapixels, warn_above_megapixels.
  • Job pending is [{n, preview, approved}] (preview is an API path); ComfyUI's internal staged id is not exposed. The ticket's {id, preview} became {n, preview}. Extra job fields: library_id, updated_at, saved: [{n, path, library_id}].
  • GET /enhance/jobs?path= returns {"jobs": [...]}, newest first.
  • POST /enhance/jobs/{id}/approve returns the bare /image/versions versions[] entry. If the file was saved but could not be ingested, it returns 202 {"linked": false, "path", "library_id", "job"}.
  • Added POST /enhance/jobs/{id}/discard (requested by FileViewer): hides the job from the per-photo list; nothing is deleted on ComfyUI.
  • Errors are {"error", "code"}: 400 bad request, 404, 410 expired, 422 ComfyUI rejected, 502, 503 unavailable/disabled.
  • requires_reference is not exposed (no startup probe).

Tests

DATABASE_URL=":memory:" cargo test: 1026 passed. Enhance tests use a mock ComfyUI HTTP server (submit mapping and seeds, lifecycle, preview relay, expiry, approve with ingest and idempotency, discard, unavailable, idle free). Fixtures are copies of the real Restore, Edit and Dev templates in tests/fixtures/enhance/. cargo fmt and cargo clippy --all-targets are clean.

Real ComfyUI (0.43.1), submitted with require_approval, never approved: Restore and Edit each went submit, poll, ready, preview (1152x864 PNG for the 019_19.JPG test photo).

Not done

  • Not deployed. A real enhance.toml must be created on the host.
  • requires_reference probing; the optional upscale-to-original-size step.

Closes #192

🤖 Generated with Claude Code

## What Enhance on demand (#192): run a ComfyUI restore/edit template on a photo from the apps, preview it through ImageApi, approve it in-app, and it lands as a photo version (#191). - `enhance.toml` (annotated `enhance.example.toml`, gitignored, no secrets): templates, path map, timings. A template missing `imageapi:source` / `imageapi:save`, or with a prompt node lacking `text|prompt|value`, is logged and skipped; the rest load. Stray `SaveImage` nodes are a startup warning. - Template fill: nodes found by `_meta.title`; `require_approval` forced; prompt `append` (per-template `prompt_join`, default one space) or `replace` (required, empty is a 400); reference node and every link to it removed when no `reference_path`; fresh value for every `seed`, `noise_seed` and `*.seed` input per submit. - Path map `/media/nas/` <-> `Z:\` (longest prefix, both directions). - `enhance_jobs` table plus a background poller (`/queue` then `/history/{id}`): queued, running, ready, failed, and `expired` when ComfyUI forgot the prompt (restart). `unavailable` after `unreachable_grace_secs`. - Idle `POST /free` once per quiet spell (empty queue, no active job, newest `/history` unchanged for `idle_free_secs`; measured on ImageApi's clock). - Approve calls `/imageapi/approve`, maps the returned path, runs a targeted ingest (`watcher::register_new_files`, extracted from `process_new_files`, plus `versions::link_new_files`), and answers with the version. Idempotent. - ImageApi never writes under library roots; ComfyUI is never exposed to the apps. API shapes are documented in CLAUDE.md ("Enhance on demand") and match FileViewer-React#57 as specified. ## Differences from the ticket text (FileViewer please note) - `GET /enhance/templates` returns an object `{available, reason?, default, warn_above_megapixels, templates: [...]}`, not a bare array. Extra per-template fields: `prompt_required`, `default`, `output_megapixels`, `warn_above_megapixels`. - Job `pending` is `[{n, preview, approved}]` (preview is an API path); ComfyUI's internal staged id is not exposed. The ticket's `{id, preview}` became `{n, preview}`. Extra job fields: `library_id`, `updated_at`, `saved: [{n, path, library_id}]`. - `GET /enhance/jobs?path=` returns `{"jobs": [...]}`, newest first. - `POST /enhance/jobs/{id}/approve` returns the bare `/image/versions` `versions[]` entry. If the file was saved but could not be ingested, it returns 202 `{"linked": false, "path", "library_id", "job"}`. - Added `POST /enhance/jobs/{id}/discard` (requested by FileViewer): hides the job from the per-photo list; nothing is deleted on ComfyUI. - Errors are `{"error", "code"}`: 400 bad request, 404, 410 expired, 422 ComfyUI rejected, 502, 503 unavailable/disabled. - `requires_reference` is not exposed (no startup probe). ## Tests `DATABASE_URL=":memory:" cargo test`: 1026 passed. Enhance tests use a mock ComfyUI HTTP server (submit mapping and seeds, lifecycle, preview relay, expiry, approve with ingest and idempotency, discard, unavailable, idle free). Fixtures are copies of the real Restore, Edit and Dev templates in `tests/fixtures/enhance/`. `cargo fmt` and `cargo clippy --all-targets` are clean. Real ComfyUI (0.43.1), submitted with require_approval, never approved: Restore and Edit each went submit, poll, ready, preview (1152x864 PNG for the 019_19.JPG test photo). ## Not done - Not deployed. A real `enhance.toml` must be created on the host. - `requires_reference` probing; the optional upscale-to-original-size step. Closes #192 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cameron added 3 commits 2026-10-30 19:41:07 +00:00
cameron force-pushed feat/192-enhance from 2d6663c12c to 97d9301a71 2026-10-30 19:41:07 +00:00 Compare
cameron merged commit c7d810b812 into master 2026-10-30 19:41:43 +00:00
cameron deleted branch feat/192-enhance 2026-10-30 19:41:43 +00:00
Sign in to join this conversation.