Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
4407650
Added backend and frontend support for a modal image search dialog
JPPhoto Feb 14, 2026
e3ebb6e
Fixed 'All Boards' selection
JPPhoto Feb 15, 2026
e6dc69f
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Feb 16, 2026
50990e1
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Feb 21, 2026
0e1eba2
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Feb 23, 2026
350326f
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Feb 24, 2026
f5bb034
Updated schema / ruff
JPPhoto Feb 24, 2026
91b45a9
ruff format
JPPhoto Feb 24, 2026
4084472
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Feb 25, 2026
ca7d671
Merge branch 'main' into search-modal
JPPhoto Feb 26, 2026
45dc4c6
Merge branch 'main' into search-modal
JPPhoto Feb 27, 2026
7672d77
Merge branch 'main' into search-modal
JPPhoto Feb 27, 2026
f404702
Fixed indentation
JPPhoto Feb 27, 2026
e99a133
Merge branch 'main' into search-modal
JPPhoto Feb 28, 2026
bed7a82
Merge branch 'main' into search-modal
JPPhoto Mar 2, 2026
30b8e73
Merge branch 'main' into search-modal
JPPhoto Mar 9, 2026
ef66566
Merge branch 'main' into search-modal
JPPhoto Mar 10, 2026
7c7b06e
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 11, 2026
fca755e
Added tests for search filters
JPPhoto Mar 11, 2026
38e64f5
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 11, 2026
fcfc94a
Merge branch 'main' into search-modal
JPPhoto Mar 20, 2026
686fed1
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 24, 2026
83c8784
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 24, 2026
00e618b
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 24, 2026
339fc06
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 26, 2026
10f16c6
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Mar 29, 2026
05b8a0e
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Apr 5, 2026
30959f2
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Apr 5, 2026
4171927
Merge branch 'invoke-ai:main' into search-modal
JPPhoto Apr 5, 2026
8f2348e
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 6, 2026
67c4013
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 6, 2026
ca9a46b
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 7, 2026
7733ae4
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 7, 2026
0f2f726
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 9, 2026
d2588b5
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 9, 2026
728f3d0
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 9, 2026
de935b6
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 10, 2026
1be5eef
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 10, 2026
4dc8274
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 10, 2026
f393f25
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 12, 2026
f1639a7
Merge remote-tracking branch 'origin/main' into search-modal
JPPhoto Apr 13, 2026
e6fdc79
chore: ruff
JPPhoto Apr 14, 2026
c8b023a
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 14, 2026
20ddcd0
Merge branch 'main' into search-modal
JPPhoto Apr 14, 2026
4eb1e8c
Merge branch 'main' into search-modal
JPPhoto Apr 14, 2026
99bca36
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 14, 2026
8ced41c
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 14, 2026
b6ff509
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 17, 2026
5c7880a
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 17, 2026
195093a
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 18, 2026
345da94
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 18, 2026
ba2ad29
Merge branch 'main' into search-modal
JPPhoto Apr 19, 2026
02045a2
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 19, 2026
114c425
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 19, 2026
a0d0f71
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 20, 2026
43cd7c4
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 20, 2026
6955e92
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 20, 2026
2c37f39
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 20, 2026
76cf6bf
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 20, 2026
e6932b0
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 21, 2026
df3e838
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 21, 2026
2f4c54b
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 21, 2026
c97ac12
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 22, 2026
97a9268
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 23, 2026
5660cbb
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 25, 2026
6eaf07c
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 25, 2026
35fd4aa
Merge remote-tracking branch 'origin/main' into search-modal
JPPhoto Apr 27, 2026
c4c991f
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
e118912
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
c650120
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
87a0f3f
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
e7a4e25
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
6bf56dc
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
9f1ff2c
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
b36291c
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 27, 2026
2ab4bd0
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto Apr 30, 2026
4dde5ce
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 1, 2026
9bbc8fc
Merge remote-tracking branch 'origin/main' into search-modal
JPPhoto May 5, 2026
fa4b40a
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 6, 2026
fda8256
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 6, 2026
86f4656
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 7, 2026
2669eb3
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 7, 2026
a266987
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 7, 2026
2bee337
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 7, 2026
0e4c38b
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
662fcf5
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
76fbdca
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
fbd4b89
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
ed6badb
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
7d9228e
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 8, 2026
ff30f00
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 9, 2026
906470e
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 9, 2026
9f2b20e
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 11, 2026
7c600fa
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 11, 2026
555cef0
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 11, 2026
d0d8aa2
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 12, 2026
6462fe8
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 12, 2026
284086d
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 12, 2026
59f2b91
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 13, 2026
14be943
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 14, 2026
d09fdef
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 15, 2026
c595e38
Merge remote-tracking branch 'origin/main' into codex-tmp/update-bran…
JPPhoto May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 118 additions & 1 deletion invokeai/app/api/routers/images.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import io
import json
import traceback
from typing import ClassVar, Optional
from typing import ClassVar, Literal, Optional

from fastapi import BackgroundTasks, Body, HTTPException, Path, Query, Request, Response, UploadFile
from fastapi.responses import FileResponse
Expand Down Expand Up @@ -38,6 +38,19 @@
IMAGE_MAX_AGE = 31536000


class ImageSearchBody(BaseModel):
file_name_term: Optional[str] = Field(default=None)
metadata_term: Optional[str] = Field(default=None)
width_min: Optional[int] = Field(default=None)
width_max: Optional[int] = Field(default=None)
width_exact: Optional[int] = Field(default=None)
height_min: Optional[int] = Field(default=None)
height_max: Optional[int] = Field(default=None)
height_exact: Optional[int] = Field(default=None)
board_ids: Optional[list[str]] = Field(default=None)
starred_mode: Literal["include", "exclude", "only"] = Field(default="include")


def _assert_image_owner(image_name: str, current_user: CurrentUserOrDefault) -> None:
"""Raise 403 if the current user does not own the image and is not an admin.

Expand Down Expand Up @@ -521,6 +534,18 @@ async def list_image_dtos(
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
starred_first: bool = Query(default=True, description="Whether to sort by starred images first"),
search_term: Optional[str] = Query(default=None, description="The term to search for"),
file_name_term: Optional[str] = Query(default=None, description="File name search term"),
metadata_term: Optional[str] = Query(default=None, description="Metadata search term"),
width_min: Optional[int] = Query(default=None, description="Minimum image width"),
width_max: Optional[int] = Query(default=None, description="Maximum image width"),
width_exact: Optional[int] = Query(default=None, description="Exact image width"),
height_min: Optional[int] = Query(default=None, description="Minimum image height"),
height_max: Optional[int] = Query(default=None, description="Maximum image height"),
height_exact: Optional[int] = Query(default=None, description="Exact image height"),
board_ids: Optional[list[str]] = Query(default=None, description="Boards to include, supports 'none'"),
starred_mode: Literal["include", "exclude", "only"] = Query(
default="include", description="How to handle starred images"
),
) -> OffsetPaginatedResults[ImageDTO]:
"""Gets a list of image DTOs for the current user"""

Expand All @@ -539,6 +564,16 @@ async def list_image_dtos(
is_intermediate,
board_id,
search_term,
file_name_term,
metadata_term,
width_min,
width_max,
width_exact,
height_min,
height_max,
height_exact,
board_ids,
starred_mode,
current_user.user_id,
)

Expand Down Expand Up @@ -776,6 +811,18 @@ async def get_image_names(
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
starred_first: bool = Query(default=True, description="Whether to sort by starred images first"),
search_term: Optional[str] = Query(default=None, description="The term to search for"),
file_name_term: Optional[str] = Query(default=None, description="File name search term"),
metadata_term: Optional[str] = Query(default=None, description="Metadata search term"),
width_min: Optional[int] = Query(default=None, description="Minimum image width"),
width_max: Optional[int] = Query(default=None, description="Maximum image width"),
width_exact: Optional[int] = Query(default=None, description="Exact image width"),
height_min: Optional[int] = Query(default=None, description="Minimum image height"),
height_max: Optional[int] = Query(default=None, description="Maximum image height"),
height_exact: Optional[int] = Query(default=None, description="Exact image height"),
board_ids: Optional[list[str]] = Query(default=None, description="Boards to include, supports 'none'"),
starred_mode: Literal["include", "exclude", "only"] = Query(
default="include", description="How to handle starred images"
),
) -> ImageNamesResult:
"""Gets ordered list of image names with metadata for optimistic updates"""

Expand All @@ -792,6 +839,16 @@ async def get_image_names(
is_intermediate=is_intermediate,
board_id=board_id,
search_term=search_term,
file_name_term=file_name_term,
metadata_term=metadata_term,
width_min=width_min,
width_max=width_max,
width_exact=width_exact,
height_min=height_min,
height_max=height_max,
height_exact=height_exact,
board_ids=board_ids,
starred_mode=starred_mode,
user_id=current_user.user_id,
is_admin=current_user.is_admin,
)
Expand All @@ -800,6 +857,66 @@ async def get_image_names(
raise HTTPException(status_code=500, detail="Failed to get image names")


@images_router.post("/search", operation_id="search_images", response_model=OffsetPaginatedResults[ImageDTO])
async def search_images(
body: ImageSearchBody,
image_origin: Optional[ResourceOrigin] = Query(default=None),
categories: Optional[list[ImageCategory]] = Query(default=None),
is_intermediate: Optional[bool] = Query(default=None),
offset: int = Query(default=0),
limit: int = Query(default=100),
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending),
starred_first: bool = Query(default=True),
) -> OffsetPaginatedResults[ImageDTO]:
return ApiDependencies.invoker.services.images.get_many(
offset=offset,
limit=limit,
starred_first=starred_first,
order_dir=order_dir,
image_origin=image_origin,
categories=categories,
is_intermediate=is_intermediate,
file_name_term=body.file_name_term,
metadata_term=body.metadata_term,
width_min=body.width_min,
width_max=body.width_max,
width_exact=body.width_exact,
height_min=body.height_min,
height_max=body.height_max,
height_exact=body.height_exact,
board_ids=body.board_ids,
starred_mode=body.starred_mode,
)


@images_router.post("/search/names", operation_id="search_image_names", response_model=ImageNamesResult)
async def search_image_names(
body: ImageSearchBody,
image_origin: Optional[ResourceOrigin] = Query(default=None),
categories: Optional[list[ImageCategory]] = Query(default=None),
is_intermediate: Optional[bool] = Query(default=None),
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending),
starred_first: bool = Query(default=True),
) -> ImageNamesResult:
return ApiDependencies.invoker.services.images.get_image_names(
starred_first=starred_first,
order_dir=order_dir,
image_origin=image_origin,
categories=categories,
is_intermediate=is_intermediate,
file_name_term=body.file_name_term,
metadata_term=body.metadata_term,
width_min=body.width_min,
width_max=body.width_max,
width_exact=body.width_exact,
height_min=body.height_min,
height_max=body.height_max,
height_exact=body.height_exact,
board_ids=body.board_ids,
starred_mode=body.starred_mode,
)


@images_router.post(
"/images_by_names",
operation_id="get_images_by_names",
Expand Down
20 changes: 20 additions & 0 deletions invokeai/app/services/image_records/image_records_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ def get_many(
is_intermediate: Optional[bool] = None,
board_id: Optional[str] = None,
search_term: Optional[str] = None,
file_name_term: Optional[str] = None,
metadata_term: Optional[str] = None,
width_min: Optional[int] = None,
width_max: Optional[int] = None,
width_exact: Optional[int] = None,
height_min: Optional[int] = None,
height_max: Optional[int] = None,
height_exact: Optional[int] = None,
board_ids: Optional[list[str]] = None,
starred_mode: Optional[str] = None,
user_id: Optional[str] = None,
is_admin: bool = False,
) -> OffsetPaginatedResults[ImageRecord]:
Expand Down Expand Up @@ -119,6 +129,16 @@ def get_image_names(
is_intermediate: Optional[bool] = None,
board_id: Optional[str] = None,
search_term: Optional[str] = None,
file_name_term: Optional[str] = None,
metadata_term: Optional[str] = None,
width_min: Optional[int] = None,
width_max: Optional[int] = None,
width_exact: Optional[int] = None,
height_min: Optional[int] = None,
height_max: Optional[int] = None,
height_exact: Optional[int] = None,
board_ids: Optional[list[str]] = None,
starred_mode: Optional[str] = None,
user_id: Optional[str] = None,
is_admin: bool = False,
) -> ImageNamesResult:
Expand Down
Loading
Loading