Skip to content

Commit 81b91a9

Browse files
Mary HippMary Hipp
authored andcommitted
remove completed_at from queue list so that created_at is only sort option, restore field values in UI
1 parent 997e619 commit 81b91a9

File tree

12 files changed

+357
-136
lines changed

12 files changed

+357
-136
lines changed

invokeai/app/api/routers/session_queue.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from invokeai.app.api.dependencies import ApiDependencies
88
from invokeai.app.services.session_processor.session_processor_common import SessionProcessorStatus
99
from invokeai.app.services.session_queue.session_queue_common import (
10-
QUEUE_ORDER_BY,
1110
Batch,
1211
BatchStatus,
1312
CancelAllExceptCurrentResult,
@@ -92,20 +91,19 @@ async def list_all_queue_items(
9291

9392
@session_queue_router.get(
9493
"/{queue_id}/item_ids",
95-
operation_id="get_queue_itemIds",
94+
operation_id="get_queue_item_ids",
9695
responses={
9796
200: {"model": ItemIdsResult},
9897
},
9998
)
10099
async def get_queue_item_ids(
101100
queue_id: str = Path(description="The queue id to perform this operation on"),
102-
order_by: QUEUE_ORDER_BY = Query(default="created_at", description="The sort field"),
103101
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
104102
) -> ItemIdsResult:
105103
"""Gets all queue item ids that match the given parameters"""
106104
try:
107105
return ApiDependencies.invoker.services.session_queue.get_queue_item_ids(
108-
queue_id=queue_id, order_by=order_by, order_dir=order_dir
106+
queue_id=queue_id, order_dir=order_dir
109107
)
110108
except Exception as e:
111109
raise HTTPException(status_code=500, detail=f"Unexpected error while listing all queue item ids: {e}")
@@ -130,7 +128,9 @@ async def get_queue_items_by_item_ids(
130128
queue_items: list[SessionQueueItem] = []
131129
for item_id in item_ids:
132130
try:
133-
queue_item = session_queue_service.get_queue_item(item_id)
131+
queue_item = session_queue_service.get_queue_item(item_id=item_id)
132+
if queue_item.queue_id != queue_id: # Auth protection for items from other queues
133+
continue
134134
queue_items.append(queue_item)
135135
except Exception:
136136
# Skip missing queue items - they may have been deleted between item id fetch and queue item fetch
@@ -376,7 +376,10 @@ async def get_queue_item(
376376
) -> SessionQueueItem:
377377
"""Gets a queue item"""
378378
try:
379-
return ApiDependencies.invoker.services.session_queue.get_queue_item(item_id)
379+
queue_item = ApiDependencies.invoker.services.session_queue.get_queue_item(item_id=item_id)
380+
if queue_item.queue_id != queue_id:
381+
raise HTTPException(status_code=404, detail=f"Queue item with id {item_id} not found in queue {queue_id}")
382+
return queue_item
380383
except SessionQueueItemNotFoundError:
381384
raise HTTPException(status_code=404, detail=f"Queue item with id {item_id} not found in queue {queue_id}")
382385
except Exception as e:

invokeai/app/invocations/mask.json

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
{
2+
"nodes": {
3+
// Input Nodes
4+
"input_image": {
5+
"type": "image",
6+
"id": "input_image",
7+
"image": "{{your_base_image}}"
8+
},
9+
"mask_image": {
10+
"type": "image",
11+
"id": "mask_image",
12+
"image": "{{your_mask_image}}"
13+
},
14+
"prompt_input": {
15+
"type": "string",
16+
"id": "prompt_input",
17+
"value": "{{your_prompt}}"
18+
},
19+
20+
// Step 1: Create mask outline/edge
21+
"mask_edge": {
22+
"type": "mask_edge",
23+
"id": "mask_edge",
24+
"image": {
25+
"node_id": "mask_image",
26+
"field": "image"
27+
},
28+
"edge_size": 8,
29+
"edge_blur": 2,
30+
"low_threshold": 50,
31+
"high_threshold": 150
32+
},
33+
34+
// Step 2: Create colored outline (optional - make outline more visible)
35+
"outline_color": {
36+
"type": "blank_image",
37+
"id": "outline_color",
38+
"width": 1024,
39+
"height": 1024,
40+
"mode": "RGB",
41+
"color": {
42+
"r": 255,
43+
"g": 0,
44+
"b": 0,
45+
"a": 255
46+
}
47+
},
48+
49+
// Step 3: Apply color to outline using multiply blend
50+
"colored_outline": {
51+
"type": "invokeai_img_blend",
52+
"id": "colored_outline",
53+
"layer_base": {
54+
"node_id": "outline_color",
55+
"field": "image"
56+
},
57+
"layer_upper": {
58+
"node_id": "mask_edge",
59+
"field": "image"
60+
},
61+
"blend_mode": "Multiply",
62+
"opacity": 1.0,
63+
"fit_to_width": true,
64+
"fit_to_height": true,
65+
"color_space": "RGB"
66+
},
67+
68+
// Step 4: Composite outline onto base image
69+
"reference_image": {
70+
"type": "invokeai_img_blend",
71+
"id": "reference_image",
72+
"layer_base": {
73+
"node_id": "input_image",
74+
"field": "image"
75+
},
76+
"layer_upper": {
77+
"node_id": "colored_outline",
78+
"field": "image"
79+
},
80+
"blend_mode": "Screen",
81+
"opacity": 0.8,
82+
"fit_to_width": true,
83+
"fit_to_height": true,
84+
"color_space": "RGB"
85+
},
86+
87+
// Step 5: Load the main model
88+
"main_model": {
89+
"type": "main_model_loader",
90+
"id": "main_model",
91+
"model": {
92+
"key": "{{your_model_key}}",
93+
"hash": "{{your_model_hash}}",
94+
"name": "{{your_model_name}}",
95+
"base": "sd-1",
96+
"type": "main"
97+
}
98+
},
99+
100+
// Step 6: Setup text conditioning
101+
"positive_conditioning": {
102+
"type": "compel",
103+
"id": "positive_conditioning",
104+
"prompt": {
105+
"node_id": "prompt_input",
106+
"field": "value"
107+
},
108+
"clip": {
109+
"node_id": "main_model",
110+
"field": "clip"
111+
}
112+
},
113+
114+
"negative_conditioning": {
115+
"type": "compel",
116+
"id": "negative_conditioning",
117+
"prompt": "blurry, low quality, distorted",
118+
"clip": {
119+
"node_id": "main_model",
120+
"field": "clip"
121+
}
122+
},
123+
124+
// Step 7: Setup IP-Adapter for reference image
125+
"ip_adapter": {
126+
"type": "ip_adapter",
127+
"id": "ip_adapter",
128+
"image": {
129+
"node_id": "reference_image",
130+
"field": "image"
131+
},
132+
"ip_adapter_model": {
133+
"key": "{{ip_adapter_model_key}}",
134+
"hash": "{{ip_adapter_model_hash}}",
135+
"name": "IP-Adapter",
136+
"base": "sd-1",
137+
"type": "ip_adapter"
138+
},
139+
"clip_vision_model": "ViT-H",
140+
"weight": 0.7,
141+
"method": "full",
142+
"begin_step_percent": 0.0,
143+
"end_step_percent": 1.0
144+
},
145+
146+
// Step 8: Generate noise
147+
"noise": {
148+
"type": "noise",
149+
"id": "noise",
150+
"seed": 42,
151+
"width": 1024,
152+
"height": 1024,
153+
"use_cpu": true
154+
},
155+
156+
// Step 9: Run denoising with reference image
157+
"denoise": {
158+
"type": "denoise_latents",
159+
"id": "denoise",
160+
"positive_conditioning": {
161+
"node_id": "positive_conditioning",
162+
"field": "conditioning"
163+
},
164+
"negative_conditioning": {
165+
"node_id": "negative_conditioning",
166+
"field": "conditioning"
167+
},
168+
"noise": {
169+
"node_id": "noise",
170+
"field": "noise"
171+
},
172+
"steps": 30,
173+
"cfg_scale": 7.5,
174+
"denoising_start": 0.0,
175+
"denoising_end": 1.0,
176+
"scheduler": "euler",
177+
"unet": {
178+
"node_id": "main_model",
179+
"field": "unet"
180+
},
181+
"ip_adapter": {
182+
"node_id": "ip_adapter",
183+
"field": "ip_adapter"
184+
}
185+
},
186+
187+
// Step 10: Convert latents to final image
188+
"final_image": {
189+
"type": "l2i",
190+
"id": "final_image",
191+
"latents": {
192+
"node_id": "denoise",
193+
"field": "latents"
194+
},
195+
"vae": {
196+
"node_id": "main_model",
197+
"field": "vae"
198+
},
199+
"tiled": false,
200+
"fp32": false
201+
}
202+
},
203+
204+
"edges": [
205+
{
206+
"source": {
207+
"node_id": "mask_image",
208+
"field": "image"
209+
},
210+
"destination": {
211+
"node_id": "mask_edge",
212+
"field": "image"
213+
}
214+
},
215+
{
216+
"source": {
217+
"node_id": "mask_edge",
218+
"field": "image"
219+
},
220+
"destination": {
221+
"node_id": "colored_outline",
222+
"field": "layer_upper"
223+
}
224+
},
225+
{
226+
"source": {
227+
"node_id": "colored_outline",
228+
"field": "image"
229+
},
230+
"destination": {
231+
"node_id": "reference_image",
232+
"field": "layer_upper"
233+
}
234+
},
235+
{
236+
"source": {
237+
"node_id": "reference_image",
238+
"field": "image"
239+
},
240+
"destination": {
241+
"node_id": "ip_adapter",
242+
"field": "image"
243+
}
244+
},
245+
{
246+
"source": {
247+
"node_id": "ip_adapter",
248+
"field": "ip_adapter"
249+
},
250+
"destination": {
251+
"node_id": "denoise",
252+
"field": "ip_adapter"
253+
}
254+
},
255+
{
256+
"source": {
257+
"node_id": "denoise",
258+
"field": "latents"
259+
},
260+
"destination": {
261+
"node_id": "final_image",
262+
"field": "latents"
263+
}
264+
}
265+
]
266+
}

invokeai/app/services/session_queue/session_queue_base.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from typing import Any, Coroutine, Optional
33

44
from invokeai.app.services.session_queue.session_queue_common import (
5-
QUEUE_ORDER_BY,
65
Batch,
76
BatchStatus,
87
CancelAllExceptCurrentResult,
@@ -149,15 +148,14 @@ def list_all_queue_items(
149148
def get_queue_item_ids(
150149
self,
151150
queue_id: str,
152-
order_by: QUEUE_ORDER_BY = "created_at",
153151
order_dir: SQLiteDirection = SQLiteDirection.Descending,
154152
) -> ItemIdsResult:
155153
"""Gets all queue item ids that match the given parameters"""
156154
pass
157155

158156
@abstractmethod
159157
def get_queue_item(self, item_id: int) -> SessionQueueItem:
160-
"""Gets a session queue item by ID"""
158+
"""Gets a session queue item by ID for a given queue"""
161159
pass
162160

163161
@abstractmethod

invokeai/app/services/session_queue/session_queue_common.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ def validate_graph(cls, v: Graph):
174174

175175
DEFAULT_QUEUE_ID = "default"
176176

177-
QUEUE_ORDER_BY = Literal["created_at", "completed_at"]
178177
QUEUE_ITEM_STATUS = Literal["pending", "in_progress", "completed", "failed", "canceled"]
179178

180179

invokeai/app/services/session_queue/session_queue_sqlite.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from invokeai.app.services.session_queue.session_queue_common import (
1111
DEFAULT_QUEUE_ID,
1212
QUEUE_ITEM_STATUS,
13-
QUEUE_ORDER_BY,
1413
Batch,
1514
BatchStatus,
1615
CancelAllExceptCurrentResult,
@@ -623,15 +622,14 @@ def list_all_queue_items(
623622
def get_queue_item_ids(
624623
self,
625624
queue_id: str,
626-
order_by: QUEUE_ORDER_BY = "created_at",
627625
order_dir: SQLiteDirection = SQLiteDirection.Descending,
628626
) -> ItemIdsResult:
629627
with self._db.transaction() as cursor_:
630628
query = f"""--sql
631629
SELECT item_id
632630
FROM session_queue
633631
WHERE queue_id = ?
634-
ORDER BY {order_by} {order_dir.value}
632+
ORDER BY created_at {order_dir.value}
635633
"""
636634
query_params = [queue_id]
637635

invokeai/frontend/web/public/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,13 +298,14 @@
298298
"completedIn": "Completed in",
299299
"batch": "Batch",
300300
"origin": "Origin",
301-
"destination": "Destination",
301+
"destination": "Dest",
302302
"upscaling": "Upscaling",
303303
"canvas": "Canvas",
304304
"generation": "Generation",
305305
"workflows": "Workflows",
306306
"other": "Other",
307307
"gallery": "Gallery",
308+
"batchFieldValues": "Batch Field Values",
308309
"item": "Item",
309310
"session": "Session",
310311
"notReady": "Unable to Queue",

0 commit comments

Comments
 (0)