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)
feat: sort action buttons by valve priority
Action buttons under assistant messages were rendered in
non-deterministic order due to set() deduplication. They now
respect the priority field from function Valves, sorted ascending
(lower value = appears first, default 0), matching the existing
filter priority mechanism.
* Allow empty LDAP Application DN value and password in General settings form
* fix(ui): use LDAP app_dn, app_dn_password with empty string instead of enforcing non-empty values
* feat: add LOG_FORMAT env var with JSON formatter for early logging
Introduce LOG_FORMAT environment variable (set to "json" to enable).
When active, logging.basicConfig() uses a JSONFormatter that outputs
single-line JSON objects with fields: ts, level, msg, caller, error,
stacktrace. This covers all log messages emitted during module imports
before Loguru's start_logger() takes over.
* feat: add JSON sink for Loguru when LOG_FORMAT=json
Add _json_sink() as a Loguru sink function that writes single-line JSON
to stdout. In start_logger(), conditionally use the JSON sink instead of
the plain-text stdout_format when LOG_FORMAT is set to "json".
* feat: suppress ASCII banner and fix alembic logging in JSON mode
- Wrap the ASCII art banner print in main.py with a LOG_FORMAT != "json"
guard so JSON output stays machine-parseable.
- Skip alembic's fileConfig() call in migrations/env.py when
LOG_FORMAT=json to prevent it from replacing the JSON log handlers
installed during early startup.