* fix: remove the cloned directory if it contains no manifest
* fix: apply feature flag guard to user extension data hosting
* fix: disable inactive controls when feature flag is off
* fix: change response status to 404
* feat: add user account version to session cookie
Co-authored-by: Copilot <copilot@github.com>
* feat: include user handle in account version hash calculation
* feat: refactor recovery code generation to use a dedicated function
* fix: don't overwrite current session version if updating another user
Co-authored-by: Copilot <copilot@github.com>
* fix: reset session version instead of nullifying the entire session
* fix: short circuit and clear cookie on request invalidation
Co-authored-by: Copilot <copilot@github.com>
* fix: update account version on recovery
---------
Co-authored-by: Copilot <copilot@github.com>
* pass jsonSchema options through sendStreamingRequest in Generate
* translate json_schema to response_format for CUSTOM chat completion source
* pass jsonSchema through generateGroupWrapper params in group chat generation
* feat: enhance asset management with extension categories
Co-authored-by: Copilot <copilot@github.com>
* fix: enhance extension name validation in server endpoints
* feat: display extension author in the extensions list
* fix: unify server error response format
Co-authored-by: Copilot <copilot@github.com>
* feat: add splash on installing third-party for the first time
* fix: add URL format validation, unify validation error messages
Co-authored-by: Copilot <copilot@github.com>
* fix: apply object freeze to EMPTY_AUTHOR value
Co-authored-by: Copilot <copilot@github.com>
* fix: typecheck extensionName in API requests
Co-authored-by: Copilot <copilot@github.com>
* feat: add feature flag guard to extensions endpoints
Co-authored-by: Copilot <copilot@github.com>
* fix: parse URL before checking
Co-authored-by: Copilot <copilot@github.com>
* fix: use case insensitive regex check
* fix: make debug log more useful
Co-authored-by: Copilot <copilot@github.com>
* fix: add pre-validation of URL format and protocol
Co-authored-by: Copilot <copilot@github.com>
* fix: leaner installation success toast
* fix: settings data loss when extensions are disabled
* fix: don't try to auto-focus elements that don't exist
Co-authored-by: Copilot <copilot@github.com>
* fix: set Popup.defaultResult to negative
Co-authored-by: Copilot <copilot@github.com>
* revert: restore undefined default result
---------
Co-authored-by: Copilot <copilot@github.com>
* fix: sanitize character filenames on V2 JSON import and harden getPngName
- Add missing sanitize() call in importFromJson V2 spec branch to match all other import paths
- Sanitize data.name before readFromV2() so the name field sync happens automatically
- Add sanitize() as defense-in-depth inside getPngName() to catch future oversights
- Refactor getPngName() to use getUniqueName() utility for consistent name generation
* fix: sanitize data.name before readFromV2 in importFromPng and importFromCharX
Same bug as importFromJson: readFromV2() overwrites the top-level name
with the unsanitized data.name, undoing any prior sanitize() call.
Fix by sanitizing data.name before readFromV2 so the sync preserves it.
* fix: sanitize top-level name field in JSON and CharX import paths
* fix: incorrect path rejection in isPathUnderParent
* fix: increase maxTries in getPngName
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat: add gemma 4 for AI studio
* fix: update max context return value for gemma-3n-e4b-it model
* refactor: iterate array of [regex, number]
* gemma4: enable tool calling and sysprompt
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Copilot <copilot@github.com>
* feat: add MiniMax as a chat completion provider
Add MiniMax (https://www.minimax.io) as a first-class chat completion
provider. MiniMax already has TTS integration in SillyTavern; this
extends support to LLM chat completions via their OpenAI-compatible API.
Supported models:
- MiniMax-M2.5 (default) — 204K context
- MiniMax-M2.5-highspeed — same capability, faster inference
Key implementation details:
- Reuses existing SECRET_KEYS.MINIMAX (shared with TTS)
- API endpoint: https://api.minimax.io/v1
- Temperature clamped to (0.0, 1.0] as required by MiniMax API
- Returns hardcoded model list since MiniMax doesn't expose /v1/models
- Full UI integration: model selector, sampler parameters, streaming
Co-Authored-By: octo-patch <octo-patch@users.noreply.github.com>
* feat: upgrade MiniMax default model to M2.7
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to model list
- Set MiniMax-M2.7 as default model
- Keep all previous models as alternatives
* feat: independent request function, vision support, temp clamping for MiniMax
- Extract sendMinimaxRequest() following Chutes pattern (PR #4844)
with function calling and JSON Schema structured output support
- Clamp temperature to (0.01, 1.0] on backend; limit frontend UI max to 1.0
- Enable image inlining for MiniMax M2.7 model
- Add MiniMax to slash-commands model selector and tokenizer mapping
- Add minimax_model to default preset
* feat: add VLM-based vision support for MiniMax M2.7
M2.7 does not natively accept image input. When images are detected
in messages, pre-process them via the MiniMax VLM endpoint
(/v1/coding_plan/vlm) to convert images to text descriptions before
sending to the chat completions API. Uses the same API key.
* feat: add M2-her model to MiniMax provider
M2-her is MiniMax's dialogue/roleplay-optimized model with 64K context
and 2048 max completion tokens. Text-only (no vision).
* feat: add MiniMax China endpoint (minimaxi.com) support
Add endpoint selector (Global/China) for MiniMax, mirroring the
SiliconFlow pattern. Users can now choose between api.minimax.io
(international) and api.minimaxi.com (China domestic).
* fix: merge consecutive same-role messages for MiniMax
MiniMax API rejects consecutive messages with the same role with
error 'invalid chat setting (2013)'. Merge them before sending.
* review: address PR feedback on MiniMax provider
Backend (src/endpoints/backends/chat-completions.js):
- Drop the entire MiniMax VLM image-preprocessing path; vision is no
longer advertised for this provider, so M2.7 messages now go straight
to /chat/completions without a separate VLM round-trip.
- Drop the json_schema -> response_format mapping (MiniMax does not
document structured-output support; relying on it was speculative).
- Drop the backend temperature clamp; the same clamp now lives in the
frontend so the wire payload matches what the user sees.
- Drop the MINIMAX branch in /status that returned a hard-coded model
list; the frontend hardcodes the same list and bypasses /status via
noValidateSources, so the round-trip was wasted.
- Add a streaming Transform + non-streaming helper that move
<think>...</think> blocks from delta.content / message.content to
reasoning_content. MiniMax M2.x emit chain-of-thought inline in
content; without this transform the raw <think> tags leak into the
rendered chat. Includes a state machine that holds back partial
marker bytes so a marker split across SSE chunks is still detected.
Frontend:
- public/scripts/openai.js: add MINIMAX to noValidateSources so the key
is accepted without a /models call; remove the dead saveModelList
branch; clamp temperature to (0.0, 1.0] in createGenerationParameters.
- public/scripts/reasoning.js: add MINIMAX to the non-streaming
reasoning_content extraction case (the backend transform now produces
this field for MiniMax responses).
- public/scripts/slash-commands.js: add MINIMAX to the /api enum and
add a MiniMax case to /api-url so users can switch endpoint by
command.
- public/scripts/custom-request.js: pass minimax_endpoint through the
override-payload merge alongside the other per-source endpoint fields.
- public/scripts/tokenizers.js: stop returning openai_model (which was
always a MiniMax model id and thus an unknown tokenizer); fall back
to gpt-3.5-turbo for a coarse but functional estimate.
- public/scripts/tool-calling.js: add MINIMAX to supportedSources so
function-calling settings are exposed.
- public/index.html: drop the "-- Connect to the API --" placeholder
option from the model select (the model list is hardcoded and always
populated); remove minimax from the vision data-source attributes
on the inline-media controls.
- public/img/minimax.svg: replace the multicolor brand SVG with a
single-color currentColor version that matches the other provider
icons in the connect panel.
* review: drop backend <think> parsing, defer to frontend
Per reviewer feedback: SillyTavern's reasoningHandler / reasoning_auto_parse
setting already extracts <think>...</think> blocks on the client side, so the
backend doesn't need to rewrite MiniMax responses. Removes the SSE Transform,
the non-streaming helper, and the corresponding case in reasoning.js.
* fix: remove isImageInliningSupported declaration for MINIMAX
* fix: remove MINIMAX from stream reasoning parsing
* fix: add to autoconnect logic
* fix: add missing MINIMAX models from docs
* fix: freq. and pres. pen aren't supported for MINIMAX
* fix: use clamp function for adjusting temperature
* fix: pass minimax_endpoint from connection profile to ChatCompletionService
* fix: update supported APIs in slash command documentation
* fix: replace bespoke merge with standard MERGE_TOOLS processing
* fix: add data-i18n attributes for headers
---------
Co-authored-by: octo-patch <octo-patch@users.noreply.github.com>
Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Display OpenRouter credit balance in UI
Adds a "View Remaining Credits" click handler that fetches the
current balance from the OpenRouter /credits endpoint via a new
server-side /api/openrouter/credits route, and renders it next
to the link. The anchor still points at openrouter.ai/account
so middle-click / right-click "open in new tab" keeps working.
* Return 500 on OpenRouter credits failure
* Reduce to two decimals
* Update view credits URL
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* fix: enhance URL validation for Z.AI image generation and handle potential delays
Fixes#5480
* fix: retry 404 in a loop
* fix: handle Z.AI image and video unavailability with appropriate warnings and responses
* feat: add bulk extension field updates with UNSET_VALUE sentinel for key deletion
- Add `UNSET_VALUE` sentinel constant to signal complete field removal from character cards
- Add `writeExtensionFieldBulk()` function to update extension fields across multiple characters in a single API call
- Add `deleteValueByPath()` utility function to remove nested object keys by dot-path
- Update `writeExtensionField()` to support `UNSET_VALUE` for deleting extension keys
- Extend `/api/characters/merge-attributes
* Revert package-lock.json changes
* Allow null values in merge-attributes filter path validation
Change filter.path existence check to only skip on undefined, not null. This allows merging attributes when the existing value is explicitly null, treating null as a valid value rather than absence of a value.
* fix: share forbiddenRegExp between modules
* feat: add writeExtensionFieldBulk and UNSET_VALUE constant to getContext
* Update src/endpoints/characters.js
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: validate for .png extension
* Update public/scripts/extensions.js
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* refactor: extract shouldSkip logic as a function param to avoid double parsing
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: extensions OpenRouter model lists
* fix: update JSDoc for optional mapping function parameter in fetchModelsByModality
* fix: update JSDoc to clarify return type of fetchModelsByModality function
* fix: encode output modality in fetchModelsByModality API request
* 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>
* 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>
* 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>
* 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
* 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
* renaming a lorebook prompts to update existing links
* used suggested api and logic
* add world property to shallow function
* Fix type error in assignLorebookToChat invoke
* Remove debug console logs
* Fix activeCharacterUpdated
* Extract updateWorldInfoLinks into a func
* Invert if for an early return
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Handle port conflicts during server startup
* Fix return type of startHTTPorHTTPS
* Update language in getAddressInUseMessage
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* Fix missing model name in tokenize requests for llama.cpp (fixes#4962)
The new router mode of llama.cpp allows to switch models on the fly,
what is already supported by SillyTavern. The call to the `/tokenize`
endpoint did not contain the model name, and failed in router mode.
This patch adds the `model` parameter similar to the implementation
for other backends.
* fix: migrate vllm and aphrodite to new payload field
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
* feat: add SiliconFlow.cn endpoint support and embedding vectors
Chat completion:
- Add endpoint selection dropdown (Global/.com vs China/.cn) to existing
SiliconFlow provider, following the Z.AI endpoint pattern
- Backend switches API URL based on selected endpoint
- Add /api-url slash command support for endpoint switching
Embeddings:
- Add SiliconFlow as a vector/embedding source (OpenAI-compatible)
- Support both .com and .cn endpoints via siliconflow_endpoint setting
borrowed from the main connection panel (Vertex AI pattern)
- Superset model list with platform attribution (.cn) markers
- Models: Qwen3-Embedding (0.6B/4B/8B) + BGE/BCE models (.cn only)
* Add filter by models type
* Load embedding models from endpoint
* Improve api-url command declaration
* Support endpoint override in custom-request service
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
The addOpenRouterSignatures function was previously converting and appending message.signature to reasoning_details unconditionally, ignoring the `enableThoughtSignatures` setting.
This change adds a check for `enableThoughtSignatures` before converting message.signature, while still ensuring the original signature property is deleted to prevent API schema validation errors (HTTP 400).
* Fix AICC direct link import parsing
Update parseAICC in src/endpoints/content-manager.js to dynamically extract the author and character name from the end of the URL path. This resolves a 404 import error caused by AICC adding category subfolders and changing their base URL structure from /character-cards/ to /charactercards/.
* Clean up whitespace in content-manager.js
Remove unnecessary whitespace in URL path processing.
* Use isValidUrl for URL validation
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>