Skip to content

feat(api): append mode for recalled reference images (+ fix recall socket double-emit)#9288

Open
lstein wants to merge 3 commits into
mainfrom
lstein/feat/recall-append-ref-images
Open

feat(api): append mode for recalled reference images (+ fix recall socket double-emit)#9288
lstein wants to merge 3 commits into
mainfrom
lstein/feat/recall-append-ref-images

Conversation

@lstein

@lstein lstein commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an append mode to the recall API for reference images, and fixes a latent double-delivery in the recall socket event that the new mode exposed.

feat(api): append mode for recalled reference images. POST /api/v1/recall/{queue_id} previously always replaced the frontend's reference-image list — the recall_parameters_updated handler dispatched refImagesRecalled with a hard-coded replace: true. This adds an append query parameter; when append=true, the recalled ip_adapters / reference_images are added to the existing list (replace: false) instead of replacing it. The flag rides inside the event's parameters dict so the generated client schema needs no regeneration, and it's injected after the persistence loop so it is never stored as a recall parameter. strict and append are mutually exclusive (400). The frontend skips the dispatch entirely when nothing resolved, so a failed append can never clear the user's current reference images.

fix(sockets): emit the recall event once to the owner+admin room union. RecallParametersUpdatedEvent was emitted in two separate socket.io calls — one to user:{user_id}, one to admin. A socket belonging to both rooms (the system user in single-user mode is also an admin, so it joins both) received the event twice. That was invisible for the idempotent scalar/replace recall fields, but the new append mode pushes rather than replaces, so each append showed up as two copies of the same reference image. Fixed by emitting once to the room union [user_room, "admin"] — python-socketio deduplicates recipients across a room list, so a socket in both rooms is delivered to exactly once while genuinely distinct owner/admin sockets each still receive it. Scoped to the recall event only; the other private events are idempotent UI updates where a double delivery is harmless.

QA Instructions

  1. Single-user mode, a model that uses reference images (FLUX.2 Klein / FLUX Kontext / Qwen Image Edit). Add one reference image.
  2. POST /api/v1/recall/default?append=true with {"reference_images": [{"image_name": "<an output image>"}]}.
  3. Expect exactly one new reference image added (the existing one preserved) — not two, and the prior entry not cleared.
  4. Repeat with ?append=false (or omitted) → the list is replaced, as before.
  5. ?strict=true&append=true → 400.

Automated: tests/app/routers/test_recall_parameters.py (append flag plumbing, strict/append mutual exclusion, not-persisted) and tests/app/routers/test_multiuser_authorization.py::TestWebSocketAuth::test_recall_parameters_emitted_once_to_owner_and_admin_rooms (single emit to the room union). Full recall + multiuser-auth suites pass (153 tests).

Merge Plan

Standard merge. The frontend change is a single dispatch in setEventListeners.tsx (no redux-slice schema change, no migration). Recommend a frontend rebuild on deploy so the append branch takes effect in the served UI.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration — N/A, no slice shape change (uses existing refImagesRecalled with replace: false)
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

🤖 Generated with Claude Code

lstein and others added 2 commits June 13, 2026 09:33
POST /api/v1/recall/{queue_id}?append=true now asks the frontend to add
the recalled reference images (ip_adapters and model-free
reference_images) to its existing list instead of replacing it. The flag
rides inside the event's parameters dict so the generated client schema
needs no regeneration, and is injected after the persistence loop so it
is never stored as a recall parameter. Mutually exclusive with strict.

The frontend dispatches refImagesRecalled with replace:false in append
mode, and skips the dispatch entirely when nothing resolved so a failed
append can never clear the user's current reference images.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RecallParametersUpdatedEvent was emitted in two separate socket.io
calls — one to the owner's user room, one to the admin room. A socket
that belongs to both (the "system" user in single-user mode is also an
admin, so it joins user:system AND admin) received the event twice.

That double delivery was invisible for the scalar/replace recall fields,
which are idempotent, but the append-mode reference-image recall pushes
rather than replaces — so each append showed up as two copies of the
same reference image in the InvokeAI canvas.

Emit once to the room union [user_room, "admin"] instead. python-socketio
deduplicates recipients across a room list, so a socket in both rooms is
delivered to exactly once, while genuinely distinct owner/admin sockets
still each receive it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added api python PRs that change python files frontend PRs that change frontend files python-tests PRs that change python tests labels Jun 13, 2026
Rebuilds the committed OpenAPI schema and generated TypeScript types so the
update_recall_parameters operation advertises the new append query
parameter. Generated via 'make frontend-openapi' / 'frontend-typegen'
equivalent; the only change is the added append param + its docstring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lstein lstein added the 6.13.5 Library Updates label Jun 13, 2026
@lstein lstein moved this to 6.13.5 LIBRARY UPDATES in Invoke - Community Roadmap Jun 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.13.5 Library Updates api frontend PRs that change frontend files python PRs that change python files python-tests PRs that change python tests

Projects

Status: 6.13.5 LIBRARY UPDATES

Development

Successfully merging this pull request may close these issues.

2 participants