- Introduced skills functionality in Chat.svelte, MessageInput.svelte, and related components.
- Added SkillsModal for displaying and managing available skills.
- Updated state management to include selectedSkillIds and integrate skills API.
- Enhanced UI to show available skills and their descriptions.
- Updated translations to support skills-related text.
getChatEventEmitter starts a setInterval emitting a `usage` socket event
every second; clearInterval ran only after sendMessageSocket resolved, so
any throw/reject left the interval firing for the page lifetime. Each
failed send added another orphaned interval, inflating server-side usage
accounting and growing CPU/memory over a session.
Wrap the send in try/finally so the interval is always cleared, on both
the happy path and any thrown/rejected path. The exception still
propagates unchanged.
Fixes#25465
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add missing custom={true} prop to AdvancedParams in General.svelte and
ModelSettingsModal.svelte so the 'Add Custom Parameter' option appears
consistently across all advanced parameter surfaces.
Also forward custom_params in the General.svelte save handler so custom
parameters are persisted instead of silently dropped on save.
Both presence_penalty and repeat_penalty in the saveHandler read from
params.frequency_penalty instead of their own values due to a
copy-paste error. This causes users adjusting either parameter to
silently save the frequency_penalty value instead.
Thread.svelte: Add null check for messagesContainerElement in scrollToBottom()
to match the existing pattern in Channel.svelte. Prevents potential TypeError
when the DOM element is not yet bound during rapid thread switches.
PinnedMessagesModal.svelte: Move res.length check inside the if (res) block.
Previously, res.length was accessed unconditionally after a guarded block,
causing TypeError when the API call fails and the .catch() returns null.
Long usernames overflow the Edit User modal, User Preview modal header,
and the sidebar user area because the flex containers lack width
constraints.
- EditUserModal: add min-w-0 to the flex-1 container so the existing
truncate class takes effect
- UserPreviewModal: add min-w-0 and truncate to the title container,
flex-shrink-0 to the close button so it stays visible
- Sidebar: add truncate to the username display and flex-shrink-0 to
the avatar container to prevent it from being squeezed
renderMermaidDiagram returned raw mermaid SVG, which FilePreview.svelte injects
via wrapper.innerHTML = svg. Mermaid runs with securityLevel: 'loose', so it
neither sanitizes click hrefs (formatUrl skips sanitizeUrl) nor DOMPurifies its
output; a .md file with a click X href "javascript:..." directive (or an
HTML-label payload) therefore executes script in the app origin when previewed.
The chat path was already safe because SVGPanZoom DOMPurifies before rendering;
file preview was not.
Sanitize at the source: renderMermaidDiagram now returns DOMPurify-cleaned SVG
via a shared sanitizeSvg helper (same policy as SVGPanZoom), so every consumer
including the FilePreview innerHTML sink receives safe output.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The lookup-prompt-by-command endpoint's only frontend wrapper,
getPromptByCommand, is dead: nothing imports or calls it, the path is
referenced nowhere else, and the route handler has no internal caller
(slash-command resolution happens client-side from the loaded prompt
list). Removes the route handler, its section header, and the dead
wrapper.
The shared Prompts.get_prompt_by_command data-layer method is kept: it
is still used by create/update prompt validation (prompts.py:175, 275,
340). PromptAccessResponse and AccessGrants are untouched.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>