Add AUDIT_INCLUDED_PATHS env var for whitelist-based audit filtering.
When set, only matching paths are audited and AUDIT_EXCLUDED_PATHS is
ignored. Auth endpoints (signin/signout/signup) are always logged
regardless of filtering mode.
* Prefer model-provided web search result count over admin default
Update `search_web` to prioritize the model-provided `count` parameter before falling back to the admin-configured `WEB_SEARCH_RESULT_COUNT`, and finally defaulting to 5.
Changes:
- Set `count` default to `None` instead of `5`.
- Adjust fallback order to: model-provided `count` → admin-configured value → `5`.
- Update comment to reflect the new precedence logic.
This ensures explicit model requests for result count are respected while preserving sensible defaults.
* Enforce maximum web search result count from config
Update `search_web` to cap the model-provided `count` parameter at the admin-configured `WEB_SEARCH_RESULT_COUNT` to prevent excessive result requests.
Changes:
- Set default `count` parameter to `5`.
- Replace fallback logic with enforcement logic that limits `count` to the configured maximum.
- Update comment to reflect that the result count is now capped to prevent abuse.
This ensures web search requests cannot exceed the configured limit while maintaining a sensible default.
Some databases contain chat records where 'history' or 'messages' are
stored as lists instead of dicts. This causes an AttributeError
('list' object has no attribute 'items') during the
8452d01d26d7_add_chat_message_table migration.
Add isinstance checks to skip chat records with unexpected data shapes
gracefully, matching the existing pattern used for individual message
validation.
Rework shimmer animation timing and gradient for a smoother sweep.
Slower start with acceleration through the text using a custom
cubic-bezier curve. Softer highlight contrast in both light and
dark modes.
Add |middletruncate:n, |start:n, and |end:n pipe filters to the
{{MESSAGES}} template variable, enabling per-message character
truncation for task models (title, tags, follow-up, etc.).
Example: {{MESSAGES:END:2|middletruncate:500}}
This optimizes task model prompt size for conversations with very
long messages (e.g. pasted documents), reducing latency for local
models and API costs.
Closes#21499
Previously, QueuedMessageItem only rendered text content and ignored
the files array, causing queued messages with only images to appear
blank. Now passes files to the component and renders image thumbnails
and file name indicators inline.
Fixes#22256
The get_token_usage_by_user query lacked group_id filtering, while the
companion get_message_count_by_user query already supported it. When an
admin filtered analytics by user group, message counts were correctly
scoped to the group but token usage totals included data from all users.
Add the group_id parameter and subquery filter to get_token_usage_by_user,
matching the pattern used by get_message_count_by_user and other analytics
queries, and pass group_id through from the analytics endpoint.
The locale for Azure TTS SSML was being extracted with `split("-")[:1]`,
which only takes the first segment (e.g., "en" from "en-US"). The
xml:lang attribute in SSML requires a full locale like "en-US", not just
a language code. This caused Azure TTS to either fail or use incorrect
pronunciation rules.
Changed `[:1]` to `[:2]` to properly extract the locale (e.g., "en-US").
Co-authored-by: gambletan <ethanchang32@gmail.com>
- URL-encodes the OAuth error message when constructing the redirect URL in the OIDC callback handler
- Without encoding, error messages containing spaces, ampersands, or other special characters produce malformed URLs that the frontend cannot parse correctly
- The custom OAuth client callback handler already correctly uses urllib.parse.quote_plus() for the same purpose; this fix brings the OIDC handler in line with that pattern
Co-authored-by: gambletan <tan@gambletan.com>
json.loads(event_data.get("user", {})) crashes with TypeError when
the "user" key is absent because the default value {} is a dict, not
a JSON string. json.loads expects str/bytes, not dict.
Also handle the case where "user" is already a dict (not serialized
JSON) to make the webhook more robust.
Co-authored-by: gambletan <ethanchang32@gmail.com>
In both inlet and outlet filter processing, response.json() was called
BEFORE response.raise_for_status(). When a filter endpoint returns an
HTTP error, the user's chat payload gets silently overwritten with the
error response body. If the error is not caught, the corrupted payload
propagates through subsequent filters and into the chat completion.
Swapped the order so raise_for_status() runs first — payload is only
updated on success.
Co-authored-by: gambletan <ethanchang32@gmail.com>
getTimeRange returns month names that are used as i18n translation keys
(consumed via \.t(chat.time_range) in the sidebar, search modal, etc.).
The keys must be exact English strings like 'January', 'February', etc.
Previously, toLocaleString('default', { month: 'long' }) was used to
generate these keys. The 'default' locale defers to the browser's locale
resolution, which in Firefox with intl.regional_prefs.use_os_locales=true
picks up OS regional settings instead of the browser language. This caused
German month names (e.g. 'Februar', 'Januar') to appear in the sidebar for
users whose OS region is set to Germany, even when both browser and app
language are set to English. Chrome was unaffected because it ignores OS
regional settings for the 'default' locale.
Since i18n has no translation key for 'Februar', the German string passed
through untranslated. Replace toLocaleString with a static MONTH_NAMES
array lookup to make the intent explicit and eliminate any browser/OS
locale dependency.