Skip to content

Commit 0f7156f

Browse files
Merge branch 'main' into main
2 parents a5d23ad + df90da2 commit 0f7156f

File tree

248 files changed

+5276
-2492
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+5276
-2492
lines changed

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
# Only affects text files and ignores other file types.
33
# For more info see: https://www.aleksandrhovhannisyan.com/blog/crlf-vs-lf-normalizing-line-endings-in-git/
44
* text=auto
5-
docker/** text eol=lf
5+
docker/** text eol=lf
6+
tests/test_model_probe/stripped_models/** filter=lfs diff=lfs merge=lfs -text

.github/workflows/frontend-checks.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ jobs:
4444
- name: check for changed frontend files
4545
if: ${{ inputs.always_run != true }}
4646
id: changed-files
47-
uses: tj-actions/changed-files@v42
47+
# Pinned to the _hash_ for v45.0.9 to prevent supply-chain attacks.
48+
# See:
49+
# - CVE-2025-30066
50+
# - https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
51+
# - https://github.com/tj-actions/changed-files/issues/2463
52+
uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8
4853
with:
4954
files_yaml: |
5055
frontend:

.github/workflows/frontend-tests.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ jobs:
4444
- name: check for changed frontend files
4545
if: ${{ inputs.always_run != true }}
4646
id: changed-files
47-
uses: tj-actions/changed-files@v42
47+
# Pinned to the _hash_ for v45.0.9 to prevent supply-chain attacks.
48+
# See:
49+
# - CVE-2025-30066
50+
# - https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
51+
# - https://github.com/tj-actions/changed-files/issues/2463
52+
uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8
4853
with:
4954
files_yaml: |
5055
frontend:

.github/workflows/python-checks.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ jobs:
4343
- name: check for changed python files
4444
if: ${{ inputs.always_run != true }}
4545
id: changed-files
46-
uses: tj-actions/changed-files@v42
46+
# Pinned to the _hash_ for v45.0.9 to prevent supply-chain attacks.
47+
# See:
48+
# - CVE-2025-30066
49+
# - https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
50+
# - https://github.com/tj-actions/changed-files/issues/2463
51+
uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8
4752
with:
4853
files_yaml: |
4954
python:

.github/workflows/python-tests.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,18 @@ jobs:
7272
PIP_USE_PEP517: '1'
7373
steps:
7474
- name: checkout
75-
uses: actions/checkout@v4
75+
# https://github.com/nschloe/action-cached-lfs-checkout
76+
uses: nschloe/action-cached-lfs-checkout@f46300cd8952454b9f0a21a3d133d4bd5684cfc2
7677

7778
- name: check for changed python files
7879
if: ${{ inputs.always_run != true }}
7980
id: changed-files
80-
uses: tj-actions/changed-files@v42
81+
# Pinned to the _hash_ for v45.0.9 to prevent supply-chain attacks.
82+
# See:
83+
# - CVE-2025-30066
84+
# - https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
85+
# - https://github.com/tj-actions/changed-files/issues/2463
86+
uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8
8187
with:
8288
files_yaml: |
8389
python:

.github/workflows/typegen-checks.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ jobs:
4242
- name: check for changed files
4343
if: ${{ inputs.always_run != true }}
4444
id: changed-files
45-
uses: tj-actions/changed-files@v42
45+
# Pinned to the _hash_ for v45.0.9 to prevent supply-chain attacks.
46+
# See:
47+
# - CVE-2025-30066
48+
# - https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
49+
# - https://github.com/tj-actions/changed-files/issues/2463
50+
uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8
4651
with:
4752
files_yaml: |
4853
src:

docs/contributing/dev-environment.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,19 @@ If you just want to use Invoke, you should use the [launcher][launcher link].
1818

1919
2. [Fork and clone][forking link] the [InvokeAI repo][repo link].
2020

21-
3. Create an directory for user data (images, models, db, etc). This is typically at `~/invokeai`, but if you already have a non-dev install, you may want to create a separate directory for the dev install.
22-
23-
4. Follow the [manual install][manual install link] guide, with some modifications to the install command:
21+
3. This repository uses Git LFS to manage large files. To ensure all assets are downloaded:
22+
- Install git-lfs → [Download here](https://git-lfs.com/)
23+
- Enable automatic LFS fetching for this repository:
24+
```shell
25+
git config lfs.fetchinclude "*"
26+
```
27+
- Fetch files from LFS (only needs to be done once; subsequent `git pull` will fetch changes automatically):
28+
```
29+
git lfs pull
30+
```
31+
4. Create an directory for user data (images, models, db, etc). This is typically at `~/invokeai`, but if you already have a non-dev install, you may want to create a separate directory for the dev install.
32+
33+
5. Follow the [manual install][manual install link] guide, with some modifications to the install command:
2434

2535
- Use `.` instead of `invokeai` to install from the current directory. You don't need to specify the version.
2636
@@ -34,27 +44,27 @@ If you just want to use Invoke, you should use the [launcher][launcher link].
3444
uv pip install -e ".[dev,test,docs,xformers]" --python 3.11 --python-preference only-managed --index=https://download.pytorch.org/whl/cu124 --reinstall
3545
```
3646
37-
5. At this point, you should have Invoke installed, a venv set up and activated, and the server running. But you will see a warning in the terminal that no UI was found. If you go to the URL for the server, you won't get a UI.
47+
6. At this point, you should have Invoke installed, a venv set up and activated, and the server running. But you will see a warning in the terminal that no UI was found. If you go to the URL for the server, you won't get a UI.
3848

3949
This is because the UI build is not distributed with the source code. You need to build it manually. End the running server instance.
4050

4151
If you only want to edit the docs, you can stop here and skip to the **Documentation** section below.
4252

43-
6. Install the frontend dev toolchain:
53+
7. Install the frontend dev toolchain:
4454

4555
- [`nodejs`](https://nodejs.org/) (v20+)
4656

4757
- [`pnpm`](https://pnpm.io/8.x/installation) (must be v8 - not v9!)
4858

49-
7. Do a production build of the frontend:
59+
8. Do a production build of the frontend:
5060

5161
```sh
5262
cd <PATH_TO_INVOKEAI_REPO>/invokeai/frontend/web
5363
pnpm i
5464
pnpm build
5565
```
5666

57-
8. Restart the server and navigate to the URL. You should get a UI. After making changes to the python code, restart the server to see those changes.
67+
9. Restart the server and navigate to the URL. You should get a UI. After making changes to the python code, restart the server to see those changes.
5868

5969
## Updating the UI
6070

invokeai/app/api/routers/workflows.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ async def list_workflows(
105105
categories: Optional[list[WorkflowCategory]] = Query(default=None, description="The categories of workflow to get"),
106106
tags: Optional[list[str]] = Query(default=None, description="The tags of workflow to get"),
107107
query: Optional[str] = Query(default=None, description="The text to query by (matches name and description)"),
108+
has_been_opened: Optional[bool] = Query(default=None, description="Whether to include/exclude recent workflows"),
108109
) -> PaginatedResults[WorkflowRecordListItemWithThumbnailDTO]:
109110
"""Gets a page of workflows"""
110111
workflows_with_thumbnails: list[WorkflowRecordListItemWithThumbnailDTO] = []
@@ -116,6 +117,7 @@ async def list_workflows(
116117
query=query,
117118
categories=categories,
118119
tags=tags,
120+
has_been_opened=has_been_opened,
119121
)
120122
for workflow in workflows.items:
121123
workflows_with_thumbnails.append(
@@ -221,14 +223,29 @@ async def get_workflow_thumbnail(
221223
raise HTTPException(status_code=404)
222224

223225

224-
@workflows_router.get("/counts", operation_id="get_counts")
225-
async def get_counts(
226-
tags: Optional[list[str]] = Query(default=None, description="The tags to include"),
226+
@workflows_router.get("/counts_by_tag", operation_id="get_counts_by_tag")
227+
async def get_counts_by_tag(
228+
tags: list[str] = Query(description="The tags to get counts for"),
227229
categories: Optional[list[WorkflowCategory]] = Query(default=None, description="The categories to include"),
228-
) -> int:
229-
"""Gets a the count of workflows that include the specified tags and categories"""
230+
has_been_opened: Optional[bool] = Query(default=None, description="Whether to include/exclude recent workflows"),
231+
) -> dict[str, int]:
232+
"""Counts workflows by tag"""
230233

231-
return ApiDependencies.invoker.services.workflow_records.get_counts(tags=tags, categories=categories)
234+
return ApiDependencies.invoker.services.workflow_records.counts_by_tag(
235+
tags=tags, categories=categories, has_been_opened=has_been_opened
236+
)
237+
238+
239+
@workflows_router.get("/counts_by_category", operation_id="counts_by_category")
240+
async def counts_by_category(
241+
categories: list[WorkflowCategory] = Query(description="The categories to include"),
242+
has_been_opened: Optional[bool] = Query(default=None, description="Whether to include/exclude recent workflows"),
243+
) -> dict[str, int]:
244+
"""Counts workflows by category"""
245+
246+
return ApiDependencies.invoker.services.workflow_records.counts_by_category(
247+
categories=categories, has_been_opened=has_been_opened
248+
)
232249

233250

234251
@workflows_router.put(

invokeai/app/invocations/compel.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040

4141
@invocation(
4242
"compel",
43-
title="Prompt",
43+
title="Prompt - SD1.5",
4444
tags=["prompt", "compel"],
4545
category="conditioning",
46-
version="1.2.0",
46+
version="1.2.1",
4747
)
4848
class CompelInvocation(BaseInvocation):
4949
"""Parse prompt using compel package to conditioning."""
@@ -233,10 +233,10 @@ def _lora_loader() -> Iterator[Tuple[ModelPatchRaw, float]]:
233233

234234
@invocation(
235235
"sdxl_compel_prompt",
236-
title="SDXL Prompt",
236+
title="Prompt - SDXL",
237237
tags=["sdxl", "compel", "prompt"],
238238
category="conditioning",
239-
version="1.2.0",
239+
version="1.2.1",
240240
)
241241
class SDXLCompelPromptInvocation(BaseInvocation, SDXLPromptInvocationBase):
242242
"""Parse prompt using compel package to conditioning."""
@@ -327,10 +327,10 @@ def invoke(self, context: InvocationContext) -> ConditioningOutput:
327327

328328
@invocation(
329329
"sdxl_refiner_compel_prompt",
330-
title="SDXL Refiner Prompt",
330+
title="Prompt - SDXL Refiner",
331331
tags=["sdxl", "compel", "prompt"],
332332
category="conditioning",
333-
version="1.1.1",
333+
version="1.1.2",
334334
)
335335
class SDXLRefinerCompelPromptInvocation(BaseInvocation, SDXLPromptInvocationBase):
336336
"""Parse prompt using compel package to conditioning."""
@@ -376,10 +376,10 @@ class CLIPSkipInvocationOutput(BaseInvocationOutput):
376376

377377
@invocation(
378378
"clip_skip",
379-
title="CLIP Skip",
379+
title="Apply CLIP Skip - SD1.5, SDXL",
380380
tags=["clipskip", "clip", "skip"],
381381
category="conditioning",
382-
version="1.1.0",
382+
version="1.1.1",
383383
)
384384
class CLIPSkipInvocation(BaseInvocation):
385385
"""Skip layers in clip text_encoder model."""

invokeai/app/invocations/controlnet_image_processors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class ControlOutput(BaseInvocationOutput):
8787
control: ControlField = OutputField(description=FieldDescriptions.control)
8888

8989

90-
@invocation("controlnet", title="ControlNet", tags=["controlnet"], category="controlnet", version="1.1.2")
90+
@invocation("controlnet", title="ControlNet - SD1.5, SDXL", tags=["controlnet"], category="controlnet", version="1.1.3")
9191
class ControlNetInvocation(BaseInvocation):
9292
"""Collects ControlNet info to pass to other nodes"""
9393

0 commit comments

Comments
 (0)