* feat: add /regex-state command to check script enabled status
Adds a new slash command that returns 'on' or 'off' to indicate whether a regex script is currently enabled or disabled.
* refactor: change /regex-state return values from 'on'/'off' to 'true'/'false'
Updates the /regex-state slash command to return boolean string values ('true'/'false') instead of ('on'/'off') for better consistency with standard boolean conventions.
* fix: include model field in sd.cpp SDAPI requests and preserve URL path
The sd.cpp integration overwrites the URL pathname when constructing
requests, which breaks proxy servers like llama-swap that use path-based
routing (e.g. /upstream/model-name). Additionally, the model field was
never included in SDAPI requests, which is required by llama-swap to
route requests to the correct backend.
Changes:
- Server: Append to URL pathname instead of overwriting (same pattern as #5178)
- Server: Pass model field through to sd-server payload
- Client: Add model name text input for sd.cpp source settings
- Client: Send model name in generate request payload
* fix: fetch models from server and populate standard Model dropdown
Instead of a separate text input for the model name, fetch the model
list from the sd.cpp server's /v1/models endpoint and populate the
standard Model dropdown. This provides a seamless experience where
users just pick a model from the dropdown like any other source.
Works with both standalone sd-server and proxy servers like llama-swap
that expose multiple models via the OpenAI-compatible models endpoint.
* fix: don't send clip_skip=1 to sd.cpp, it produces blank images
sd-server generates blank white images when clip_skip is set to 1.
Since clip_skip=1 means 'use all CLIP layers' (the default behavior),
only send the parameter when it's > 1.
* Fix eslint
* Replace string appends with urlJoin
* fix: convert URL strings to URL objects in sdcpp routes
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Extends the #logDeprecated helper to accept and log the arguments passed to deprecated methods, providing better debugging context for migration. Updates all deprecated method calls (get, has, registerMacro, unregisterMacro) to forward their arguments to the deprecation logger.
Prevents invalid CSS by skipping rules containing `::` (pseudo-elements like `::before`, `::after`, `::-webkit-scrollbar`) when converting `:hover` to `:focus-visible`, as pseudo-elements cannot receive focus.
Previously only exact 'en' was accepted as fallback when a language wasn't found. Now accepts any English variant (en-US, en-AU, etc.) to prevent spurious warnings for valid English locales.
* feat: add Workers AI text embeddings and multimodal captioning
Extends the Cloudflare Workers AI integration to the vectors and
caption extensions.
Embeddings: adds workers_ai source to the vectors extension using the
OpenAI-compatible /v1/embeddings endpoint, with dynamic model listing
from the Cloudflare model search API.
Captioning: adds workers_ai as a multimodal caption API with dynamic
vision model discovery via the multimodal-models endpoint.
* Add logo svg
* Refactor caption dropdown population
* Fix order of sources
* feat: add error handling for missing Workers AI account ID
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* refactor(tts): remove redundant 4-space codeblock filter
- Deleted the regex that removed lines starting with four spaces.
- Original intent was to strip "indented code blocks" (Markdown legacy syntax).
- In practice, SillyTavern already handles explicit code fences (```...``` and ~~~...~~~).
- Indented code blocks are rarely used and the regex caused unnecessary text loss in normal messages.
- Simplifies codeblock skipping logic and avoids accidental removal of valid content.
* Remove commented out code
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat: add entry preview to world info deletion confirmation dialog
Displays entry comment or first two lines of content in the deletion confirmation popup to help users verify they're deleting the correct entry.
* fix: sanitize world info entry preview text in deletion confirmation dialog
Adds DOMPurify sanitization to the entry preview text displayed in the deletion confirmation popup to prevent potential XSS vulnerabilities from unsanitized user content.
* DOMPurify -> escapeHtml
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat: add Cloudflare Workers AI provider
Adds support for Cloudflare Workers AI using its OpenAI-compatible API.
Workers AI-specific stuff includes:
- Model list fetching and capabilities detection
- Tokenizer auto-detection for typical hosted model families
- Streaming not supported when using structured output
Closes#5305
* Make the entire header clickable
* Add missing samplers
* Fix non-streaming reasoning parsing
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Add unit tests for prompt-converters.js
* fix: add type annotation for prompt-converters module
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Skip TTS for voices explicitly set to disabled (fixes#4970)
* Always show disabled message in commands and fix restoring voice map UI
* Always show a message on manual TTS trigger
* Fix null current job on disabled
* Adjust type annotation
* Force update worker when disabled play is attempted
* Treat audio control queue as manual
* Update TTS message processing to include manual flag
* Don't show toast if was already shown by manual playback
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Use custom init script instead of postinstall
* Revert changes to start scripts in src\electron
* Add global data to content manager
* Add migration for public overrides and user.css location update
* Update npm publish workflow to use 'omit=dev' flag in npm ci commands
* Rename user.css readme file
* Fix indentation in userCssMiddleware function
* Add directory creation for content target
* Restore template compile location
* Move stylesheet up in index.json
* Use path.resolve for user.css file path in userCssMiddleware
* Correct capitalization in "Not Found" error page title and heading
* Remove init run from startup scripts
* Simplify user CSS file path resolution
* Update userCssMiddleware comment
* Use custom init script instead of postinstall
* Revert changes to start scripts in src\electron
* feat: add --ignore-scripts flag to npm install commands in batch and shell scripts
* feat: add --ignore-scripts flag to npm ci in Dockerfile
* fix: require long press to open swipe picker on phones
* fix: clarify parameter description in assignLorebookToChat function
* fix: update event parameter type in onSwipeCounterClick to include TouchEvent
* fix: update event parameter types in onSwipeCounterClick and addLongPressEvent
* fix: return Error objects from invokeFunctionTool and create error invocations
invokeFunctionTool previously called .toString() on caught errors,
converting them to plain strings. This made the instanceof Error
check in invokeFunctionTools dead code.
Changes:
- Return Error objects directly from invokeFunctionTool
- Create error invocations with error: true flag when tools fail
- Record failed stealth tools in stealthCalls
- Preserve signature/reasoning on error invocations
- Add error field to ToolInvocation typedef
* fix: use Error.toString to avoid behavioral changes
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat(secrets): update readSecret function to accept optional secret ID
* add secret_id to ConnectionManagerRequestService payload
* fix: pass secret_id for Text Completion types
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
The delete handler had a missing `return` before `sendStatus(400)`,
causing execution to fall through to `sendStatus(200)`, a double-send
that triggers ERR_HTTP_HEADERS_SENT, which the catch block then
compounds by attempting a third `sendStatus(500)`.
Both the delete and download handlers used callback-based `fs.unlink()`
without awaiting completion. In the download handler, this caused a race
with `createWriteStream({ flags: 'wx' })` (which fails if the file
still exists). In both handlers, `throw err` inside the callback was an
unhandled exception that could never be caught by the outer try/catch.
Replace callback-based `fs.unlink()` with `await fs.promises.unlink()`
and add missing `return` statements to prevent response cascades.
* fix: conditionally include secrets in user data backup
* feat: add full data backup toggle
* 418 -> 403
I'm not a teapot
* Distinguish fails from disabled
* feat(ui): add popup to jump to a specific swipe
Adds a new "Jump to swipe history" button to message actions and makes
the swipe counter clickable on the latest message. This opens a
searchable popup allowing users to quickly find and jump to a
specific alternate swipe without having to click through them
sequentially.
- Adds a searchable swipe picker popup menu
- Makes the swipe counter interactive when multiple swipes exist
- Adds a dedicated swipe picker button to message controls
* fix(ui): hide swipe picker when there are no swipes
Ensures the newly added swipe picker button is only shown when a
message has multiple swipes available. It explicitly hides the
button for non-swipeable messages or messages with a single swipe.
* feat(ui): redesign swipe picker with direct id input
Replace text-based search with a numeric input for direct swipe navigation.
Update popup layout with a sticky header and improved scrolling behavior.
Sync input value with the currently selected swipe in the list.
Refactor styling to align with chat selection components.
* feat(ui): allow branching from specific swipes via picker
- Enable swipe picker for historical messages to inspect alternate swipes
- Add branch button to picker entries to create new chats from specific swipes
- Update saveChat and createBranch to accept chat snapshots
- Restrict swipe jumping to the active message only
* refactor(logic): consolidate swipe sync logic and simplify helpers
Update `syncSwipeToMes` to accept a target message object, enabling its
use in the bookmarks module and removing the duplicate
`applySwipeToSnapshot` function.
Also simplify `canOpenSwipePickerForMessage` and
`canJumpToSwipeForMessage` signatures by removing the redundant message
parameter.
* refactor(a11y): support dynamic roles via classes
Introduce a managed role system in the accessibility script to handle
elements that dynamically gain or lose interactive states. The mutation
observer now watches for class attribute changes and automatically
applies or clears roles (e.g., `role="button"`) using active selectors.
Updated the swipe counter to rely on this centralized system by toggling
an `.interactable` class instead of manually modifying tabindex and role
attributes. Removed the redundant 'Enter' keydown handler for the swipe
counter to prevent duplicate trigger events.
* fix(ui): compute missing token counts in swipe picker
Update renderSwipeList to asynchronously calculate token counts when
missing from swipe metadata. Introduce SWIPE_SOURCE.SWIPE_PICKER to
correctly identify swipes triggered from the picker and bypass
generation checks.
* feat(ui): enable deleting specific swipes via swipe picker
- Adds a delete button to swipe picker entries, allowing removal of specific message versions.
- Refactors deletion logic to handle removing non-current swipes without triggering animations and correctly updates indices.
- Includes confirmation dialogs and improves input focus behavior.
* refactor:Delete process inline to button click processor
* feat: universal swipe inspection and picker improvements
- Permit opening the swipe browser on any chat entry to review past generations.
- Parallelize the retrieval of token statistics to speed up list rendering.
- Format message metrics (length and tokens) into a single, concise string.
- Update the `getBranchChatSnapshot` API to accept an options object.
- Register swipe list items as interactable elements for keyboard control.
- Apply styling to prevent text highlighting on picker entries.
* fix:remove unused CSS
* fix: fix disabled styling for swipe delete button
Remove tooltips and prevent hover animations or glow effects when the
delete button is disabled in the swipe picker. Update CSS to enforce
default cursor and fixed opacity on hover for the disabled state.
* remove: Unused CSS
* Extract swipe-picker.js module
* Revert to manual ARIA role management
* Avoid scrollIntoView and scroll on open
* Fix keyboard interaction in past chats menu
* Fix a11y attribute
* fix: call refreshSwipeButtons when deleting not selected swipe
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat: add finalizeIntermediaryMessage for streaming tool call chains
Add a lighter finalization method on StreamingProcessor that runs
before tool invocation. This ensures CHARACTER_MESSAGE_RENDERED is
emitted for streamed text messages before the tool call chain
continues, allowing extensions (TTS, image forwarding, etc.) to
process intermediary messages.
finalizeIntermediaryMessage performs essential processing:
- Code block styling (addCopyToCodeBlocks)
- Reasoning handler finalization
- Logprobs saving
- Image attachment processing
- Reasoning signature storage
- MESSAGE_RECEIVED and CHARACTER_MESSAGE_RENDERED events
Without the heavier onFinishStreaming operations:
- UI unlock (markUIGenStopped)
- Auto-swipe
- Sound playback
- Chat saving
- Swipe counter update
* fix: return Error objects from invokeFunctionTool and create error invocations
invokeFunctionTool previously called .toString() on caught errors,
converting them to plain strings. This made the 'instanceof Error'
check in invokeFunctionTools dead code - errors silently became
successful invocations, showToolCallError never fired, and the
result.errors array was always empty.
Changes:
- Return Error objects directly from invokeFunctionTool
- Create error invocations with error: true flag when tools fail
- Add error field to ToolInvocation typedef
* fix: record failed stealth tools in stealthCalls and preserve signature/reasoning on error invocations
When a stealth tool errors, its name was not added to stealthCalls, causing
shouldStopGeneration to evaluate as false. This led to an incorrect recursive
Generate('normal') call instead of stopping generation as the stealth tool
contract requires ('no follow-up generation').
Also preserve toolCall.signature and reasoningText on error invocations to
match the success path, preventing Gemini/OpenRouter multi-turn tool context
from breaking when a tool call fails.
* Clarify method comments
* fix: initialize error property in ToolInvocation to false
* Apply review suggestions
* Make options object required
* fix: remove unnecessary return statement in updateSwipeCounter method
* refactor: split tool call error handling into separate PR (#5351)
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>