Commit Graph

18872 Commits

Author SHA1 Message Date
Josh Corbett
7eaf1d5bd0
New Documentation Fixes (#9061)
* fix(docs): swap `docs-new` to `docs`

also renames `docs` to `docs-old`, purely for preservation purposes.

* feat(docs): clarify compel syntax availability

---------

Co-authored-by: joshistoast <me@joshcorbett.com>
2026-04-17 08:10:10 -04:00
Josh Corbett
9643b1385f
Docs Overhaul (#8896)
* feat(docs): new docs scaffold

* feat(docs): update alternate launchers section

* feat(docs): add contributor section

* fix(docs): update description of lynxhub launcher mention

* feat(docs): add more docs

* feat(docs): setup index page

* feat(docs): add more docs, rewrote a few pages

* feat(docs): add todo

* feat(docs): set up internationalization

* fix(docs): admonition typo

* feat(docs): add invoke styles

* feat(docs): add more invoke styling, revamp splash page, remove theme
switcher

* fix(docs): expressive code sh styles without title

* chore(docs): cleanup readme

* chore(docs): add new github pages workflow

* fix(docs): remove base path

* chore(docs): add initial translations CI, powered by Crowdin

* feat(docs): upgrade astro

* feat(docs): enhance new contributor guide

* feat(docs): various enhancements

- improve homepage;
- enhance some docs pages;
- override some layout components;
- enhance interactivity and qol styling;
- create new download page + component;
- add llms.txt;
- remove unused logo component;

* feat(docs): isolate new docs

* style(docs): use md reference links over utility links

* chore(docs): specify package manager

* feat(docs): releases page

* feat(docs): add page context menus

* feat(docs): sort workflows sidebar items

* fix(docs): relative links on homepage

* feat(docs): add text tool and recall params api guides

* feat(docs): fix faq links, create models concept page

* chore(docs): set CI to new dir, update deployment url

* feat(docs): generate settings and api json for pages

- update deploy script
- add api and settings component to render generated json
- increase page content width

* style(docs): remove relative path for component import

* fix(docs): resolve tests by regenerating json

* fix(docs): fixing the test for real this time

- sorts openapi output map required field
- missing `__name__` attributes
- resolved components name keyerror

* feat(docs): finish 'adding nodes' page

* feat(docs): upgrade astro + starlight, add link tester

* chore(docs): upgrade astro

* feat(docs): add prompting guides

* fix(docs): generated openapi

* fix(docs): ci node version

* fix(docs): invalid links

* fix(docs): md aside formatting

* feat(docs): reorder 'configuration' category

* feat(docs): change contributor checklist to steps list

* chore(docs): upgrade deps

* feat(docs): splash page image styling

* feat(docs): add gallery marquee to homepage

* feat(docs): add splash page marquee gallery

* feat(docs): remove openapi generation

* fix(docs): regenerate settings json

* fix(docs): json generation test

---------

Co-authored-by: joshistoast <me@joshcorbett.com>
Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-04-16 22:03:05 -04:00
Weblate (bot)
3fc981f4b6
ui: translations update from weblate (#9051)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
Co-authored-by: 嶋田豪介 <shimada_gosuke@cyberagent.co.jp>
Co-authored-by: Lucas Prone <sac2087@gmail.com>
2026-04-14 14:42:57 -04:00
Lincoln Stein
e252a5bb47
fix(multiuser): make preexisting workflows visible after migration (#9049) 2026-04-14 12:27:14 -04:00
kappacommit
ce896678d7
List Supported Models In Readme (#9038)
* List models in readme

* list API models

* Update README.md

---------

Co-authored-by: Your Name <you@example.com>
2026-04-14 15:47:18 +00:00
Weblate (bot)
37ff6c3743
ui: translations update from weblate (#9036)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2210 of 2259 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2224 of 2272 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2252 of 2295 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2264 of 2309 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Russian)

Currently translated at 60.7% (1419 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2290 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2319 of 2372 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2327 of 2380 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2328 of 2382 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2370 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Finnish)

Currently translated at 1.5% (37 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/fi/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2373 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 87.1% (2120 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 92.2% (2244 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Spanish)

Currently translated at 29.4% (720 of 2444 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/es/

* translationBot(ui): update translation (Italian)

Currently translated at 97.6% (2405 of 2464 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.2% (2471 of 2540 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.1% (2476 of 2548 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
Co-authored-by: 嶋田豪介 <shimada_gosuke@cyberagent.co.jp>
Co-authored-by: Lucas Prone <sac2087@gmail.com>
2026-04-14 11:40:15 -04:00
Valeri Che
1b50c1a79c
Feat(UI): Replace prompt window resize handle with bottom edge drag handle. (#8975)
* feat(ui): replace prompt window resize handle with bottom-edge drag handle

* Fix: removed unused export

---------

Co-authored-by: Josh Corbett <joshwcorbett@icloud.com>
2026-04-14 01:10:35 +00:00
Alexander Eichhorn
acd4157bdf
feat(ui): add canvas project save/load (.invk format) (#8917)
* feat(ui): add canvas project save/load (.invk format)

Add ZIP-based .invk file format to save and restore the entire canvas
state including all layers, masks, reference images, generation
parameters, LoRAs, and embedded image files. Images are deduplicated
on load - only missing images are re-uploaded from the project file.
- Always clear LoRAs on project load, even when project has none
- Fix jszip dependency ordering in package.json
- Add useAssertSingleton to SaveCanvasProjectDialog for consistency
- Add concurrency limit (max 5) for image fetch/upload requests
- Remove redundant deep-clone in remapCroppableImage (mutate in-place)
- Default project name to "Canvas Project" instead of empty string

* Chore pnpm fix
2026-04-14 01:01:57 +00:00
Alexander Eichhorn
06a1881bbd
feat(ui): group nodes by category in add-node dialog (#8912)
* feat(ui): group nodes by category in add-node dialog

Add collapsible category grouping to the node picker command palette.
Categories are parsed from the backend schema and displayed as
expandable sections with caret icons. All categories auto-expand
when searching.

* feat(ui): add toggle for category grouping in add-node dialog and prioritize exact matches

Add a persistent "Group Nodes by Category" setting to workflow editor settings,
allowing users to switch between grouped and flat node list views. Also sort
exact title matches to the top when searching.

* fix: update test schema categories to match expected templates

* feat: add expand/collapse all buttons to node picker and fix node categories

Add "Expand All" and "Collapse All" link-buttons above the grouped
category list in the add-node dialog so users can quickly open or
close all categories at once. Buttons are hidden during search since
categories auto-expand while searching.

Fix two miscategorized nodes: Z-Image ControlNet was in "Control"
instead of "Controlnet", and Upscale (RealESRGAN) was in "Esrgan"
instead of "Upscale".

* refactor(nodes): clean up node category taxonomy

Reorganize all built-in invocation categories into a consistent set of
18 groups (model, prompt, conditioning, controlnet_preprocessors,
latents, image, mask, inpaint, tiles, upscale, segmentation, math,
strings, primitives, batch, metadata, multimodal, canvas).

- Move denoise/i2l/l2i nodes consistently into "latents"
- Move all mask creation/manipulation nodes into "mask"
- Split ControlNet preprocessors out of "controlnet" into their own group
- Fold "unet", "vllm", "string", "ip_adapter", "t2i_adapter" into larger
  groups
- Move metadata_linked denoise wrappers from "latents" to "metadata"
- Add missing category to ideal_size
- Introduce dedicated "canvas" group for canvas/output/panel nodes

Also adds the now-required `category` field to invocation template
fixtures in validateConnection.test.ts.

* Chore Ruff Format

---------

Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-14 00:38:47 +00:00
Valeri Che
441821ca03
Feat(canvas): Add Lasso Tool with Freehand and Polygon modes (#8908)
* Feat(Canvas): Add Lasso tool with Freehand and Polygon modes

* Refine Lasso modes behavior and optimisation.

* Fix: Pettier

* added docs/features/Lasso_tool.md

* Fix: Removed restrictions mentioned in PR's conversation:
1. Disabled when there is no visible raster content
2. Lasso is blocked when all inpaint masks are globally hidden.

---------

Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-14 00:22:34 +00:00
Valeri Che
9d62bfdf8e
Feature: Add optional setting to prune queue on startup (#8861)
* Add more settings to invokeai.yaml for improved queue management.

* Adjusted description

* More logic tweaking

* chore(api): update generated schema types

* chore(api): update generated schema types

* Add: UI element for max_queue_history to 'Settings' modal.
Now it is possible to set Max queue history in both places: .yaml and UI.

* chore(api): regenerate schema types

* chore(api): normalize generated schema path defaults

---------

Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-14 00:15:29 +00:00
Jonathan
dd056067a9
Added workflow connectors (#9027)
* Add persisted workflow connectors

* Polish workflow connector menu and visuals

* Refine connector sizing and alignment

* Fix connector deletion and unresolved constraints

* Format connector deletion tests

* Revert frontend test config tweaks

* Address workflow connector review feedback

* Format workflow flow menu memo
2026-04-13 20:03:59 -04:00
Lincoln Stein
33ec16deb4
Feature: Shared/private workflows and image boards in multiuser mode (#9018)
* feat: Per-user workflow libraries in multiuser mode (#114)

* Add per-user workflow isolation: migration 28, service updates, router ownership checks, is_public endpoint, schema regeneration, frontend UI

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* feat: add shared workflow checkbox to Details panel, auto-tag, gate edit/delete, fix tests

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* Restrict model sync to admin users only (#118)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* feat: distinct splash screens for admin/non-admin users in multiuser mode (#116)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* Disable Save when editing another user's shared workflow in multiuser mode (#120)

* Disable Save when editing another user's shared workflow in multiuser mode

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* chore(app): ruff

* Add board visibility (private/shared/public) feature with tests and UI

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* Enforce read-only access for non-owners of shared/public boards in UI

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* Fix remaining board access enforcement: invoke icon, drag-out, change-board filter, archive

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* fix: allow drag from shared boards to non-board targets (viewer, ref image, etc.)

Previously, images in shared boards owned by another user could not be
dragged at all — the draggable setup was completely skipped in
GalleryImage.tsx when canWriteImages was false. This blocked ALL drop
targets including the viewer, reference image pane, and canvas.

Now images are always draggable. The board-move restriction is enforced
in the dnd target isValid functions instead:
- addImageToBoardDndTarget: rejects moves from shared boards the user
  doesn't own (unless admin or board is public)
- removeImageFromBoardDndTarget: same check

Other drop targets (viewer, reference images, canvas, comparison, etc.)
remain fully functional for shared board images.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(security): add auth requirement to all sensitive routes in multimodal mode

* chore(backend): ruff

* fix (backend): improve user isolation for session queue and recall parameters

 - Sanitize session queue information of all cross-user fields except for the timestamps and status.
 - Recall parameters are now user-scoped.
 - Queue status endpoints now report user-scoped activity rather than global activity
 - Tests added:

  TestSessionQueueSanitization (4 tests):
  1. test_owner_sees_all_fields - Owner sees complete queue item data
  2. test_admin_sees_all_fields - Admin sees complete queue item data
  3. test_non_owner_sees_only_status_timestamps_errors -
     Non-owner sees only item_id, queue_id, status, and timestamps; everything else is redacted
  4. test_sanitization_does_not_mutate_original - Sanitization doesn't modify the original object

  TestRecallParametersIsolation (2 tests):

  5. test_user1_write_does_not_leak_to_user2 - User1's recall params are not visible in user2's client state
  6. test_two_users_independent_state - Both users can write recall params independently without overwriting each other

fix(backend): queue status endpoints report user-scoped stats rather than global stats

* fix(workflow): do not filter default workflows in multiuser mode

  Problem: When categories=['user', 'default'] (or no category filter)
  and user_id was set for multiuser scoping, the SQL query became
     WHERE category IN ('user', 'default') AND user_id = ?,
     which  excluded default workflows (owned by "system").

  Fix: Changed user_id = ? to (user_id = ? OR category = 'default') in
  all 6 occurrences across workflow_records_sqlite.py — in get_many,
  counts_by_category, counts_by_tag, and get_all_tags. Default
  workflows are now always visible regardless of user scoping.

  Tests added (2):
  - test_default_workflows_visible_when_listing_user_and_default — categories=['user','default'] includes both
  - test_default_workflows_visible_when_no_category_filter — no filter still shows defaults

* fix(multiuser): scope queue/recall/intermediates endpoints to current user

Several read-only and event-emitting endpoints were leaking aggregate
cross-user activity in multiuser mode:

- recall_parameters_updated event was broadcast to every queue
  subscriber. Added user_id to the event and routed it to the owner +
  admin rooms only.
- get_queue_status, get_batch_status, counts_by_destination and
  get_intermediates_count now scope counts to the calling user
  (admins still see global state). Removed the now-redundant
  user_pending/user_in_progress fields and simplified QueueCountBadge.
- get_queue_status hides current item_id/session_id/batch_id when the
  current item belongs to another user.

Also fixes test_session_queue_sanitization assertions that lagged
behind the recently expanded redaction set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(backend): ruff

* fix(multiuser): reject anonymous websockets and scope queue item events

Close three cross-user leaks in the websocket layer:

- _handle_connect() now rejects connections without a valid JWT in
  multiuser mode (previously fell through to user_id="system"), so
  anonymous clients can no longer subscribe to queue rooms and observe
  other users' activity. In single-user mode it still accepts as system
  admin.
- _handle_sub_queue() no longer silently falls back to the system user
  for an unknown sid in multiuser mode; it refuses the subscription.
- QueueItemStatusChangedEvent and BatchEnqueuedEvent are now routed to
  user:{user_id} + admin rooms instead of the full queue room. Both
  events carry unsanitized user_id, batch_id, origin, destination,
  session_id, and error metadata and must not be broadcast.
- BatchEnqueuedEvent gains a user_id field; emit_batch_enqueued and
  enqueue_batch thread it through.

New TestWebSocketAuth suite covers connect accept/reject for both
modes, sub_queue refusal, and private routing of the queue item and
batch events (plus a QueueClearedEvent sanity check).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): verify user record on websocket connect

A deleted or deactivated user with an unexpired JWT could still open a
websocket and subscribe to queue rooms. Now _handle_connect() checks the
backing user record (exists + is_active) in multiuser mode, mirroring
the REST auth path in auth_dependencies.py. Fails closed if the user
service is unavailable.

Tests: added deleted-user and inactive-user rejection tests; updated
valid-token test to create the user in the database first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): close bulk download cross-user exfiltration path

Backend:
- POST /download now validates image read access (per-image) and board
  read access (per-board) before queuing the download.
- GET /download/{name} is intentionally unauthenticated because the
  browser triggers it via <a download> which cannot carry Authorization
  headers. Access control relies on POST-time checks, UUID filename
  unguessability, private socket event routing, and single-fetch deletion.
- Added _assert_board_read_access() helper to images router.
- Threaded user_id through bulk download handler, base class, event
  emission, and BulkDownloadEventBase so events carry the initiator.
- Bulk download service now tracks download ownership via _download_owners
  dict (cleaned up on delete).
- Socket bulk_download room subscription restricted to authenticated
  sockets in multiuser mode.
- Added error-catching in FastAPIEventService._dispatch_from_queue to
  prevent silent event dispatch failures.

Frontend:
- Fixed pre-existing race condition where the "Preparing Download" toast
  from the POST response overwrote the "Ready to Download" toast from the
  socket event (background task completes in ~17ms, so the socket event
  can arrive before Redux processes the HTTP response). Toast IDs are now
  distinct: "preparing:{name}" vs "{name}".
- bulk_download_complete/error handlers now dismiss the preparing toast.

Tests (8 new):
- Bulk download by image names rejected for non-owner (403)
- Bulk download by image names allowed for owner (202)
- Bulk download from private board rejected (403)
- Bulk download from shared board allowed (202)
- Admin can bulk download any images (202)
- Bulk download events carry user_id
- Bulk download event emitted to download room
- GET /download unauthenticated returns 404 for unknown files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): enforce board visibility on image listing endpoints

GET /api/v1/images?board_id=... and GET /api/v1/images/names?board_id=...
passed board_id directly to the SQL layer without checking board
visibility. The SQL only applied user_id filtering for board_id="none"
(uncategorized images), so any authenticated user who knew a private
board ID could enumerate its images.

Both endpoints now call _assert_board_read_access() before querying,
returning 403 unless the caller is the board owner, an admin, or the
board is Shared/Public.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(backend): ruff

* fix(multiuser): require image ownership when adding images to boards

add_image_to_board and add_images_to_board only checked write access to
the destination board, never verifying that the caller owned the source
image.  An attacker could add a victim's image to their own board, then
exploit the board-ownership fallback in _assert_image_owner to gain
delete/patch/star/unstar rights on the image.

Both endpoints now call _assert_image_direct_owner which requires direct
image ownership (image_records.user_id) or admin — board ownership is
intentionally not sufficient, preventing the escalation chain.

Also fixed a pre-existing bug where HTTPException from the inner loop in
add_images_to_board was caught by the outer except-Exception and returned
as 500 instead of propagating the correct status code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(backend): ruff

* fix(multiuser): validate image access in recall parameter resolution

The recall endpoint loaded image files and ran ControlNet preprocessors
on any image_name supplied in control_layers or ip_adapters without
checking that the caller could read the image.  An attacker who knew
another user's image UUID could extract dimensions and, for supported
preprocessors, mint a derived processed image they could then fetch.

Added _assert_recall_image_access() which validates read access for every
image referenced in the request before any resolution or processing
occurs.  Access is granted to the image owner, admins, or when the image
sits on a Shared/Public board.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): require admin auth on model install job endpoints

list_model_installs, get_model_install_job, pause, resume,
restart_failed, and restart_file were unauthenticated — any caller who
could reach the API could view sensitive install job fields (source,
local_path, error_traceback) and interfere with installation state.

All six endpoints now require AdminUserOrDefault, consistent with the
neighboring cancel and prune routes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): close bulk download exfiltration and additional review findings

Bulk download capability token exfiltration:
- Socket events now route to user:{user_id} + admin rooms instead of the
  shared 'default' room (the earlier toast race that blocked this approach
  was fixed in a prior commit).
- GET /download/{name} re-requires CurrentUserOrDefault and enforces
  ownership via get_owner().
- Frontend download handler replaced <a download> (which cannot carry auth
  headers) with fetch() + Authorization header + programmatic blob download.

Additional fixes from reviewer tests:
- Public boards now grant write access in _assert_board_write_access and
  mutation rights in _assert_image_owner (BoardVisibility.Public).
- Uncategorized image listing (GET /boards/none/image_names) now filters
  to the caller's images only, preventing cross-user enumeration.
- board_images router uses board_image_records.get_board_for_image()
  instead of images.get_dto() to avoid dependency on image_files service.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): add user_id scoping to workflow SQL mutations

Defense-in-depth: the route layer already checks ownership before
calling update/delete/update_is_public/update_opened_at, but the SQL
statements did not include AND user_id = ?, so a bypass of the route
check would allow cross-user mutations.

All four methods now accept an optional user_id parameter.  When
provided, the SQL WHERE clause is scoped to that user.  The route layer
passes current_user.user_id for non-admin callers and None for admins.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(multiuser): allow non-owner uploads to public boards

upload_image() blocked non-owner uploads even to public boards.  The
board write check now allows uploads when board_visibility is Public,
consistent with the public-board semantics in _assert_board_write_access
and _assert_image_owner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jonathan <34005131+JPPhoto@users.noreply.github.com>
2026-04-13 17:27:20 -04:00
Lincoln Stein
b42274a57e
Feat[model support]: Qwen Image — full pipeline with edit, generate LoRA, GGUF, quantization, and UI (#9000) 2026-04-12 14:39:13 +02:00
Alexander Eichhorn
a3507121da
feat: add configurable shift parameter for Z-Image (#9004)
* feat: add configurable shift parameter for Z-Image sigma schedule

Add a shift (mu) override to the Z-Image denoise invocation and expose
it in the UI. When left blank, shift is auto-calculated from image
dimensions (existing behavior). Users can override to fine-tune the
timestep schedule, with an inline X button to reset back to auto.

* refactor: switch Z-Image sigma schedule from exponential to linear time shift

Use shift directly as a linear multiplier instead of exp(mu), giving
more predictable and uniform control over the timestep schedule.
Auto-calculated values are converted via exp(mu) to preserve identical
default behavior.

* feat: recall Z-Image shift parameter from metadata

Write z_image_shift into graph metadata and add a ZImageShift recall
handler so the shift override can be restored from previously generated
images. Auto-mode (null) is omitted from metadata to avoid persisting a
stale value.

---------

Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-04-10 02:16:53 +00:00
Josh Corbett
3c9b282a90
Redesign Model Manager Installation Queue (#8910)
* feat(model manager): redesign queue

* feat(model manager queue): improve ui/ux

- standardized table row widths
- sticky table header
- reverse table data direction (new items on top)
- queue empty state
- ui and icon tweaks
- add progress tooltip
- add code comments for sanity

* fix(model manager queue): add missing imports

dammit zed editor

* fix(model manager queue): play/pause button condition

* feat(model manager queue): remove backend status badge

* fix(model manager queue): remove unused useStore import

* fix(model manager queue): prettier lint

* feat(model meneger queue): backend disconnected visual feedback

* fix(model manager queue): qol list item ui tweaks

* feat(model manager queue): reorganize bulk actions

* feat(model manager queue): tweak column widths

* feat(model manager queue): disable actions dropdown if items disabled

* feat(model manager queue): optimistic updated and code qulity

- Treated downloads_done as an active install phase for row UI and bulk cancel.
- Stopped stale error text from overriding the badge after resume/restart by only showing the error label when
  the displayed status is actually error.
- Added row-level action locking to block duplicate pause/resume/cancel/restart submissions.
- Added optimistic row status handling so the UI does not briefly fall back to stale error/restart state
  before RTK Query/socket updates arrive.
- Fixed local-path basename parsing for both the main row title and restart-required file rows.
- Added an accessible aria-label to the overflow menu button.

* style(model manager queue): fix prettier lint

* feat(model manager queue): keep prune action visible

* feat(model manager queue): prune button ui tweak

---------

Co-authored-by: joshistoast <me@joshcorbett.com>
Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-04-10 02:05:01 +00:00
Lincoln Stein
a2e4fbb9b5
fix: patch openapi-typescript enum generation to match OpenAPI schema (#9037)
openapi-typescript computes enum types from `const` usage in
discriminated unions rather than from the enum definition itself,
dropping values that only appear in some union members (e.g. "anima"
from BaseModelType). Add a post-processing step that patches generated
string enum types to match the actual OpenAPI schema definitions.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Alexander Eichhorn <alex@eichhorn.dev>
2026-04-10 01:59:49 +00:00
Alexander Eichhorn
06eff38354
fix(ui): replace all hardcoded frontend strings with i18n translation keys (#9013)
* fix(ui): replace all hardcoded frontend strings with i18n translation keys

Remove fallback/defaultValue strings from t() calls, replace hardcoded
English text in labels, tooltips, aria-labels, placeholders and JSX content
with proper t() calls, and add ~50 missing keys to en.json. Fix incorrect
i18n key paths in CanvasObjectImage.ts and a Zoom button aria-label bug
in CanvasToolbarScale.tsx.

* chore pnpm run fix

---------

Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-04-10 01:46:25 +00:00
Jonathan
d4104be0b8
graph.py refactoring and If node optimization (#9030)
* test: add if-node execution coverage

* feat: short-circuit if-node branch execution

* test: cover iterated if-node pruning

* style: apply ruff fixes for if-node work

* refactor: track prepared exec node metadata

* fix: defer iterated if branches until resolution

* refactor: extract prepared exec registry

* refactor: extract if branch scheduler

* refactor: extract execution materializer

* refactor: extract execution scheduler

* refactor: extract execution runtime

* refactor: clarify if branch resolution

* refactor: clarify execution materialization

* docs: describe graph execution helpers

* refactor: clarify execution runtime

* refactor: clarify execution scheduling

* refactor: clarify iteration node selection

* docs: describe execution materializer flow

* refactor: clarify collector validation

* refactor: clarify iterator validation

* refactor: clarify graph validation flow

* docs: update shared graph design overview

* chore: typegen

* fix: harden if-node scheduler edge cases
2026-04-09 21:38:40 -04:00
Jonathan
ee600973ed
Broaden text encoder partial-load recovery (#9034) 2026-04-09 20:09:40 -04:00
Weblate (bot)
d4c0e631e2
ui: translations update from weblate (#9028)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2210 of 2259 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2224 of 2272 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2252 of 2295 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2264 of 2309 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Russian)

Currently translated at 60.7% (1419 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2290 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2319 of 2372 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2327 of 2380 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2328 of 2382 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2370 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Finnish)

Currently translated at 1.5% (37 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/fi/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2373 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 87.1% (2120 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 92.2% (2244 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Spanish)

Currently translated at 29.4% (720 of 2444 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/es/

* translationBot(ui): update translation (Italian)

Currently translated at 97.6% (2405 of 2464 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
Co-authored-by: 嶋田豪介 <shimada_gosuke@cyberagent.co.jp>
Co-authored-by: Lucas Prone <sac2087@gmail.com>
2026-04-09 22:17:09 +00:00
Lincoln Stein
5f35d0e432
feat(frontend): suppress tooltips on touch devices (#9001)
* feat(frontend): suppress tooltips on touch devices

* fix(frontend): change selector to role="tooltip" because .chakra-tooltip does not match

* chore(frontend): lint:prettier
2026-04-09 21:56:25 +00:00
4pointoh
f0d09c34a8
feat: add Anima model support (#8961)
* feat: add Anima model support

* schema

* image to image

* regional guidance

* loras

* last fixes

* tests

* fix attributions

* fix attributions

* refactor to use diffusers reference

* fix an additional lora type

* some adjustments to follow flux 2 paper implementation

* use t5 from model manager instead of downloading

* make lora identification more reliable

* fix: resolve lint errors in anima module

Remove unused variable, fix import ordering, inline dict() call,
and address minor lint issues across anima-related files.

* Chore Ruff format again

* fix regional guidance error

* fix(anima): validate unexpected keys after strict=False checkpoint loading

Capture the load_state_dict result and raise RuntimeError on unexpected
keys (indicating a corrupted or incompatible checkpoint), while logging
a warning for missing keys (expected for inv_freq buffers regenerated
at runtime).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): make model loader submodel fields required instead of Optional

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): add Classification.Prototype to LoRA loaders, fix exception types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): fix replace-all in key conversion, warn on DoRA+LoKR, unify grouping functions

- Use key.replace(old, new, 1) in _convert_kohya_unet_key and _convert_kohya_te_key to avoid replacing multiple occurrences
- Upgrade DoRA+LoKR dora_scale strip from logger.debug to logger.warning since it represents data loss
- Replace _group_kohya_keys and _group_by_layer with a single _group_keys_by_layer function parameterized by extra_suffixes, with _KOHYA_KNOWN_SUFFIXES and _PEFT_EXTRA_SUFFIXES constants
- Add test_empty_state_dict_returns_empty_model to verify empty input produces a model with no layers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): add safety cap for Qwen3 sequence length to prevent OOM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): add denoising range validation, fix closure capture, add edge case tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): add T5 to metadata, fix dead code, decouple scheduler type guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(anima): update VAE field description for required field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: regenerate frontend types after upstream merge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: ruff format anima_denoise.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(anima): add T5 encoder metadata recall handler

The T5 encoder was added to generation metadata but had no recall
handler, so it wasn't restored when recalling from metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(frontend): add regression test for buildAnimaGraph

Add tests for CFG gating (negative conditioning omitted when cfgScale <= 1)
and basic graph structure (model loader, text encoder, denoise nodes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* only show 0.6b for anima

* dont show 0.6b for other models

* schema

* Anima preview 3

* fix ci

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: kappacommit <samwolfe40@gmail.com>
Co-authored-by: Alexander Eichhorn <alex@eichhorn.dev>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-04-09 12:04:11 -04:00
Alexander Eichhorn
60d0bcdbc1
Feature(UI): Canvas Workflow Integration - Run Workflow on Raster Layer (#8665)
* feat: Add canvas-workflow integration feature

This commit implements a new feature that allows users to run workflows
directly from the unified canvas. Users can now:

- Access a "Run Workflow" option from the canvas layer context menu
- Select a workflow with image parameters from a modal dialog
- Customize workflow parameters (non-image fields)
- Execute the workflow with the current canvas layer as input
- Have the result automatically added back to the canvas

Key changes:
- Added canvasWorkflowIntegrationSlice for state management
- Created CanvasWorkflowIntegrationModal and related UI components
- Added context menu item to raster layers
- Integrated workflow execution with canvas image extraction
- Added modal to global modal isolator

This integration enhances the canvas by allowing users to leverage
custom workflows for advanced image processing directly within the
canvas workspace.

Implements feature request for deeper workflow-canvas integration.

* refactor(ui): simplify canvas workflow integration field rendering

- Extract WorkflowFieldRenderer component for individual field rendering
- Add WorkflowFormPreview component to handle workflow parameter display
- Remove workflow compatibility filtering - allow all workflows
- Simplify workflow selector to use flattened workflow list
- Add comprehensive field type support (String, Integer, Float, Boolean, Enum, Scheduler, Board, Model, Image, Color)
- Implement image field selection UI with radio

* feat(ui): add canvas-workflow-integration logging namespace

* feat(ui): add workflow filtering for canvas-workflow integration

- Add useFilteredWorkflows hook to filter workflows with ImageField inputs
- Add workflowHasImageField utility to check for ImageField in Form Builder
- Only show workflows that have Form Builder with at least one ImageField
- Add loading state while filtering workflows
- Improve error messages to clarify Form Builder requirement
- Update modal description to mention Form Builder and parameter adjustment
- Add fallback error message for workflows without Form Builder

* feat(ui): add persistence and migration for canvas workflow integration state

- Add _version field (v1) to canvasWorkflowIntegrationState for future migrations
- Add persistConfig with migration function to handle version upgrades
- Add persistDenylist to exclude transient state (isOpen, isProcessing, sourceEntityIdentifier)
- Use es-toolkit isPlainObject and tsafe assert for type-safe migration
- Persist selectedWorkflowId and fieldValues across sessions

* pnpm fix imports

* fix(ui): handle workflow errors in canvas staging area and improve form UX

- Clear processing state when workflow execution fails at enqueue time
  or during invocation, so the modal doesn't get stuck
- Optimistically update listAllQueueItems cache on queue item status
  changes so the staging area immediately exits on failure
- Clear processing state on invocation_error for canvas workflow origin
- Auto-select the only unfilled ImageField in workflow form
- Fix image field overflow and thumbnail sizing in workflow form

* feat(ui): add canvas_output node and entry-based staging area

Add a dedicated `canvas_output` backend invocation node that explicitly
marks which images go to the canvas staging area, replacing the fragile
board-based heuristic. Each `canvas_output` node produces a separate
navigable entry in the staging area, allowing workflows with multiple
outputs to be individually previewed and accepted.

Key changes:
- New `CanvasOutputInvocation` backend node (canvas.py)
- Entry-based staging area model where each output image is a separate
  navigable entry with flat next/prev cycling across all items
- Frontend execute hook uses `canvas_output` type detection instead of
  board field heuristic, with proper board field value translation
- Workflow filtering requires both Form Builder and canvas_output node
- Updated QueueItemPreviewMini and StagingAreaItemsList for entries
- Tests for entry-based navigation, multi-output, and race conditions

* Chore pnp run fix

* Chore eslint fix

* Remove unused useOutputImageDTO export to fix knip lint

* Update invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/useCanvasWorkflowIntegrationExecute.tsx

Co-authored-by: dunkeroni <dunkeroni@gmail.com>

* move UI text to en.json

* fix conflicts merge with main

* generate schema

* Chore typegen

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-07 03:25:06 +00:00
Alexander Eichhorn
80be1b7282
fix: correct inaccurate download size estimates in starter models (#8968)
Verified model sizes against Hugging Face repositories and corrected
11 descriptions that had wrong or outdated download size estimates.

Key corrections:
- T5-XXL base encoder: ~8GB → ~9.5GB
- FLUX.2 VAE: ~335MB → ~168MB (was confused with FLUX.1 VAE)
- FLUX.1 Krea dev: ~33GB → ~29GB (uses quantized T5, not full)
- FLUX.2 Klein 4B/9B Diffusers: ~10GB/~20GB → ~16GB/~35GB
- SD3.5 Medium/Large: ~15GB/~19G → ~16GB/~28GB
- CogView4: ~29GB → ~31GB
- Z-Image Turbo: ~30.6GB → ~33GB
- FLUX.1 Kontext/Krea quantized: ~14GB → ~12GB
2026-04-07 03:09:29 +00:00
Alexander Eichhorn
dbbf28925b
fix: detect FLUX.2 Klein 9B Base variant via filename heuristic (#9011)
Klein 9B Base (undistilled) and Klein 9B (distilled) have identical
architectures and cannot be distinguished from the state dict alone.
Use a filename heuristic ("base" in the name) to detect the Base
variant for checkpoint, GGUF, and diffusers format models.

Also fixes the incorrect guidance_embeds-based detection for diffusers
format, since both variants have guidance_embeds=False.
2026-04-07 02:31:33 +00:00
Alexander Eichhorn
f08b802968
feat: add support for OneTrainer BFL Flux LoRA format (#8984)
* feat: add support for OneTrainer BFL Flux LoRA format

Newer versions of OneTrainer export Flux LoRAs using BFL internal key
names (double_blocks, single_blocks, img_attn, etc.) with a
'transformer.' prefix and split QKV projections (qkv.0/1/2, linear1.0/1/2/3).
This format was not recognized by any existing detector.

Add detection and conversion for this format, merging split QKV and
linear1 layers into MergedLayerPatch instances for the fused BFL model.

* chore ruff
2026-04-07 02:04:48 +00:00
Alexander Eichhorn
ae42182246
fix: detect Z-Image LoRAs with transformer.layers prefix (#8986)
OneTrainer exports Z-Image LoRAs with 'transformer.layers.' key prefix
instead of 'diffusion_model.layers.'. Add this prefix (and the
PEFT-wrapped 'base_model.model.transformer.layers.' variant) to the
Z-Image LoRA probe so these models are correctly identified and loaded.
2026-04-07 01:52:06 +00:00
Weblate (bot)
32002bd37e
ui: translations update from weblate (#8992)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2210 of 2259 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2224 of 2272 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2252 of 2295 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2264 of 2309 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Russian)

Currently translated at 60.7% (1419 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2290 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2319 of 2372 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2327 of 2380 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2328 of 2382 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2370 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Finnish)

Currently translated at 1.5% (37 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/fi/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2373 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 87.1% (2120 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 92.2% (2244 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Spanish)

Currently translated at 29.4% (720 of 2444 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/es/

---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
Co-authored-by: 嶋田豪介 <shimada_gosuke@cyberagent.co.jp>
Co-authored-by: Lucas Prone <sac2087@gmail.com>
2026-04-05 23:54:25 -04:00
Jonathan
e6f2980d7c
Added If node and ability to link an Any output to a node input if cardinality matches (#8869)
* Added If node

* Added stricter type checking on inputs

* feat(nodes): make if-node type checks cardinality-aware without loosening global AnyField

* chore: typegen
2026-04-06 03:26:26 +00:00
Lincoln Stein
01c67c5468
Fix (multiuser): Ask user to log back in when security token has expired (#9017)
* Initial plan

* Warn user when credentials have expired in multiuser mode

Agent-Logs-Url: https://github.com/lstein/InvokeAI/sessions/f0947cda-b15c-475d-b7f4-2d553bdf2cd6

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* Address code review: avoid multiple localStorage reads in base query

Agent-Logs-Url: https://github.com/lstein/InvokeAI/sessions/f0947cda-b15c-475d-b7f4-2d553bdf2cd6

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* bugfix(multiuser): ask user to log back in when authentication token expires

* feat: sliding window session expiry with token refresh

Backend:
- SlidingWindowTokenMiddleware refreshes JWT on each mutating request
  (POST/PUT/PATCH/DELETE), returning a new token in X-Refreshed-Token
  response header. GET requests don't refresh (they're often background
  fetches that shouldn't reset the inactivity timer).
- CORS expose_headers updated to allow X-Refreshed-Token.

Frontend:
- dynamicBaseQuery picks up X-Refreshed-Token from responses and
  updates localStorage so subsequent requests use the fresh expiry.
- 401 handler only triggers sessionExpiredLogout when a token was
  actually sent (not for unauthenticated background requests).
- ProtectedRoute polls localStorage every 5s and listens for storage
  events to detect token removal (e.g. manual deletion, other tabs).

Result: session expires after TOKEN_EXPIRATION_NORMAL (1 day) of
inactivity, not a fixed time after login. Any user-initiated action
resets the clock.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(backend): ruff

* fix: address review feedback on auth token handling

Bug fixes:
- ProtectedRoute: only treat 401 errors as session expiry, not
  transient 500/network errors that should not force logout
- Token refresh: use explicit remember_me claim in JWT instead of
  inferring from remaining lifetime, preventing silent downgrade of
  7-day tokens to 1-day when <24h remains
- TokenData: add remember_me field, set during login

Tests (6 new):
- Mutating requests (POST/PUT/DELETE) return X-Refreshed-Token
- GET requests do not return X-Refreshed-Token
- Unauthenticated requests do not return X-Refreshed-Token
- Remember-me token refreshes to 7-day duration even near expiry
- Normal token refreshes to 1-day duration
- remember_me claim preserved through refresh cycle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(backend): ruff

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jonathan <34005131+JPPhoto@users.noreply.github.com>
2026-04-05 23:11:44 -04:00
Jonathan
be015a5434
Run vitest during frontend build (#9022)
* Run vitest during frontend build

* Add frontend-test Make target
2026-04-05 19:18:24 -04:00
Valeri Che
82f3dc9032
Fix to retain layer opacity on mode switch. (#8879)
Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-05 22:33:47 +00:00
Alexander Eichhorn
471ab9d9c0
feat: add Inpaint Mask as drag & drop target on canvas (#8942)
Closes #8843

Co-authored-by: dunkeroni <dunkeroni@gmail.com>
2026-04-05 21:59:44 +00:00
Jonathan
41a542552e
Fix workflows info copy focus (#9015)
* Fix workflow copy hotkeys in info view

* Fix Makefile help target copy

* Fix workflow info view copy handling

* Fix workflow edge delete hotkeys
2026-04-05 18:32:35 +00:00
Jonathan
5596fa0cc8
Upgrade spandrel version (#8996)
* Upgrade spandrel to 0.4.2 in uv.lock

* Fixed typos
2026-04-05 14:28:15 -04:00
Valeri Che
05f4deb68c
Feat(Canvas): Add button to hide preview stage thumbnails (#8963)
* Feat(Canvas): Add button to hide preview thumbnails in staging area.

* Code clean up. Added tests.

* Fix: Removed redundant Icon aliases
2026-04-04 23:58:45 +00:00
Alexander Eichhorn
474d85e5e0
feat: add bulk reidentify action for models (#8951) (#8952)
* feat: add bulk reidentify action for models (#8951)

Add a "Reidentify Models" bulk action to the model manager, allowing
users to re-probe multiple models at once instead of one by one.

- Backend: POST /api/v2/models/i/bulk_reidentify endpoint with partial
  failure handling (returns succeeded/failed lists)
- Frontend: bulk reidentify mutation, confirmation modal with warning
  about custom settings reset, toast notifications for all outcomes
- i18n: new translation keys for bulk reidentify UI strings

* fix typgen

* Fix bulk reidentify failing for models without trigger_phrases

The bulk reidentify endpoint was directly assigning trigger_phrases
without checking if the config type supports it, causing an
AttributeError for ControlNet models. Added the same hasattr guard
used by the individual reidentify endpoint. Also restored the
missing path preservation that the individual endpoint has.
2026-04-04 20:43:57 +00:00
Lincoln Stein
ed268b1cfc
Feature (frontend): Add invisible watermark decoder node. (#8967)
* Initial plan

* Add invisible watermark decoding node and utility method

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>

* chore(frontend): typegen

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
2026-04-04 20:00:21 +00:00
Jonathan
6963cd97ba
Fix SIGINT shutdown during active inference (#8993) 2026-03-28 18:35:18 -04:00
Lincoln Stein
ab6f186f8c
chore: bump version to 6.12.0.post1 (#8990)
* (chore) bump version to 6.12.0.post1
2026-03-25 22:00:13 -04:00
Lincoln Stein
7f2878f691
Fix(frontend): Make ordering of multiple FLUX.2 reference images deterministic (#8989) 2026-03-24 09:52:50 -04:00
Weblate (bot)
d32f6b5a56
ui: translations update from weblate (#8985)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2210 of 2259 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2224 of 2272 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2252 of 2295 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2264 of 2309 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Russian)

Currently translated at 60.7% (1419 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2290 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2319 of 2372 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2327 of 2380 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2328 of 2382 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2370 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Finnish)

Currently translated at 1.5% (37 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/fi/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2373 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Japanese)

Currently translated at 87.1% (2120 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ja/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2374 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
Co-authored-by: 嶋田豪介 <shimada_gosuke@cyberagent.co.jp>
2026-03-23 23:09:57 -04:00
Jonathan
f7aa5fcbbf
Add chaining to Collect node (#8933)
* Add chained collect node

* test(frontend): align parseSchema fixtures with collect v1.1 and normalize undefined fields in assertions

* fix(nodes): block collect-to-collect links when inferred item types differ

---------

Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
2026-03-24 01:39:52 +00:00
Lincoln Stein
438515bf9a
Chore: Bump version to 6.12.0 (#8981)
* chore: bump version to 6.12.0

* chore: update What's New text
2026-03-23 20:20:01 -04:00
dunkeroni
17da6bb9c3
Fix(UI): Replace boolean submenu icon with PiIntersectSquareBold (#8962)
* change submenu icon to phosphor

* Use PiIntersectSquareBold
2026-03-15 11:14:35 -04:00
Weblate (bot)
b120ef5183
ui: translations update from weblate (#8956)
* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2205 of 2250 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2210 of 2259 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.8% (2224 of 2272 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2252 of 2295 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 98.0% (2264 of 2309 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Russian)

Currently translated at 60.7% (1419 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/

* translationBot(ui): update translation (Italian)

Currently translated at 98.1% (2290 of 2334 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2319 of 2372 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2327 of 2380 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.7% (2328 of 2382 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2370 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

* translationBot(ui): update translation (Finnish)

Currently translated at 1.5% (37 of 2429 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/fi/

* translationBot(ui): update translation (Italian)

Currently translated at 97.5% (2373 of 2433 strings)

Translation: InvokeAI/Web UI
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/

---------

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Co-authored-by: DustyShoe <warukeichi@gmail.com>
Co-authored-by: Ilmari Laakkonen <ilmarille@gmail.com>
2026-03-15 11:01:09 -04:00
Jonathan
dc5007fe95
Fix/model cache Qwen/CogView4 cancel repair (#8959)
* Repair partially loaded Qwen models after cancel to avoid device mismatches

* ruff

* Repair CogView4 text encoder after canceled partial loads

* Avoid MPS CI crash in repair regression test

* Fix MPS device assertion in repair test
2026-03-15 10:04:15 -04:00
Alexander Eichhorn
bba207a856
fix(ui): IP adapter / control adapter model recall for reinstalled models (#8960)
* fix(ui): resolve models by name+base+type when recalling metadata for reinstalled models

When a model (IP Adapter, ControlNet, etc.) is deleted and reinstalled,
it gets a new UUID key. Previously, metadata recall would fail because
it only looked up models by their stored UUID key. Now the recall falls
back to searching by name+base+type, allowing reinstalled models with
the same name to be correctly resolved.

https://claude.ai/code/session_01XYubzMK363BXGTvfJJqFnX

* Add hash-based model recall fallback for reinstalled models

When a model is deleted and reinstalled, it gets a new UUID key but
retains the same BLAKE3 content hash. This adds hash as a middle
fallback stage in model resolution (key → hash → name+base+type),
making recall more robust.

Changes:
- Add /api/v2/models/get_by_hash backend endpoint (uses existing
  search_by_hash from model records store)
- Add getModelConfigByHash RTK Query endpoint in frontend
- Add hash fallback to both resolveModel and parseModelIdentifier

https://claude.ai/code/session_01XYubzMK363BXGTvfJJqFnX

* Chore pnpm fix

* Chore typegen

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-11 17:59:47 +00:00
Alexander Eichhorn
a7b367fda2
fix: only delete individual LoRA file instead of entire parent directory (#8954)
When deleting a file-based model (e.g. LoRA), the previous logic used
rmtree on the parent directory, which would delete all files in that
folder — even unrelated ones. Now only the specific model file is
removed, and the parent directory is cleaned up only if empty afterward.
2026-03-10 22:33:08 +00:00