Skip to content

Commit 5c403fb

Browse files
authored
fix: resolve valve priority for actions and filters via class instantiation (open-webui#21841)
fix: resolve valve priority for actions and filters via class instantiation The priority sorting for action buttons and filter execution order read valve data directly from the database JSON column using Functions.get_function_valves_by_id(). This returns only explicitly saved values — when a developer defines priority as a class default in their Valves definition (e.g. priority: int = 5) without ever opening the Valves UI to persist it, the database column remains empty. Every function then resolves to priority 0, and the preceding set() deduplication produces non-deterministic iteration order that the stable sort preserves — resulting in random button placement on every page load. The fix instantiates the Valves class with database values as keyword overrides: Valves(**(db_valves or {})). This merges any persisted overrides onto the code-defined defaults, matching the pattern already established in the action execution handler, filter processing pipeline, and tool module initialization. A secondary sort key (the function ID) ensures fully deterministic ordering even when multiple functions share the same priority value. Affected locations: - get_action_priority in utils/models.py (action button ordering) - get_priority in utils/filter.py (filter execution ordering)
1 parent 538501c commit 5c403fb

2 files changed

Lines changed: 19 additions & 8 deletions

File tree

backend/open_webui/utils/filter.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ def get_function_module(request, function_id, load_from_db=True):
2222

2323
def get_sorted_filter_ids(request, model: dict, enabled_filter_ids: list = None):
2424
def get_priority(function_id):
25-
function = Functions.get_function_by_id(function_id)
26-
if function is not None:
27-
valves = Functions.get_function_valves_by_id(function_id)
28-
return valves.get("priority", 0) if valves else 0
25+
try:
26+
function_module = get_function_module(request, function_id)
27+
if function_module and hasattr(function_module, "Valves"):
28+
valves_db = Functions.get_function_valves_by_id(function_id)
29+
valves = function_module.Valves(**(valves_db if valves_db else {}))
30+
return getattr(valves, "priority", 0)
31+
except Exception:
32+
pass
2933
return 0
3034

3135
filter_ids = [function.id for function in Functions.get_global_filter_functions()]
@@ -50,7 +54,7 @@ def get_active_status(filter_id):
5054
]
5155

5256
filter_ids = [fid for fid in filter_ids if fid in active_filter_ids]
53-
filter_ids.sort(key=get_priority)
57+
filter_ids.sort(key=lambda fid: (get_priority(fid), fid))
5458

5559
return filter_ids
5660

backend/open_webui/utils/models.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,16 +332,23 @@ def get_filter_items_from_module(function, module):
332332
meta[key] = copy.deepcopy(value)
333333

334334
def get_action_priority(action_id):
335-
valves = Functions.get_function_valves_by_id(action_id)
336-
return valves.get("priority", 0) if valves else 0
335+
try:
336+
function_module = request.app.state.FUNCTIONS.get(action_id)
337+
if function_module and hasattr(function_module, "Valves"):
338+
valves_db = Functions.get_function_valves_by_id(action_id)
339+
valves = function_module.Valves(**(valves_db if valves_db else {}))
340+
return getattr(valves, "priority", 0)
341+
except Exception:
342+
pass
343+
return 0
337344

338345
for model in models:
339346
action_ids = [
340347
action_id
341348
for action_id in list(set(model.pop("action_ids", []) + global_action_ids))
342349
if action_id in enabled_action_ids
343350
]
344-
action_ids.sort(key=get_action_priority)
351+
action_ids.sort(key=lambda aid: (get_action_priority(aid), aid))
345352

346353
filter_ids = [
347354
filter_id

0 commit comments

Comments
 (0)