Skip to content

docs: add Scalattice custom endpoint - #740

Open
romulushill wants to merge 13 commits into
LibreChat-AI:mainfrom
scalattice:feat/add-scalattice-endpoint
Open

docs: add Scalattice custom endpoint#740
romulushill wants to merge 13 commits into
LibreChat-AI:mainfrom
scalattice:feat/add-scalattice-endpoint

Conversation

@romulushill

Copy link
Copy Markdown

Summary

Add a Scalattice page under AI Endpoints.

OpenAI-compatible marketplace at https://api.scalattice.cloud/v1. Keys from https://scalattice.cloud/docs/developers. models.fetch: true so LibreChat can pull the live catalog.

romulushill and others added 13 commits August 28, 2026 08:07
Document Scalattice as an OpenAI-compatible custom endpoint with live catalog fetch.
…eChat-AI#744)

* fix: retry the alias transition before skipping a cache purge

Asset discovery treated a 404 from an in-flight Vercel alias swap as
fatal, so the first automatic purge after live discovery shipped aborted
without issuing a single Cloudflare call, and the new build's assets kept
their poisoned edge entries in whichever locations had cached the 404.

Retry the two observable symptoms of a transition, a probe 404 and page
shells that disagree about the Webpack runtime, and let a run that still
cannot enumerate assets purge its recovery targets rather than nothing.
A degraded run records no purge marker, so the next deploy re-purges its
range instead of stepping over it.

* fix: discover build assets without a Webpack runtime map

Builds of this project can serve /_next/static/immutable/** with no
webpack-*.js runtime chunk, which discovery treated as a hard failure and
which would therefore stop every asset purge. Fall back to the eagerly
referenced shell assets, and warn that the lazy-chunk map could not be
expanded so the coverage loss is visible in the run.

Identify which build rendered a shell by the Skew Protection deployment
id when Next.js publishes one, falling back to the runtime chunk name.
The deployment id works in either asset layout, so transition detection
no longer depends on webpack output.

Verified against both live layouts: 105 assets from production, 78 from
an immutable-layout preview deployment.

* fix: harden cache asset recovery

* fix: type concurrent cache probes
* docs: prepare v0.8.8-rc2 release

* docs: cover late v0.8.8-rc2 fixes

* docs: cover latest v0.8.8-rc2 changes

* docs: split v0.8.8-rc2 config changelog

* docs: cover latest v0.8.8-rc2 changes

* docs: include agents v3.7.17 release fix
…LibreChat-AI#754)

The npm card on /docs/local advertised Node.js v20.19+ and `npm ci` as the
install step. Both are wrong:

- LibreChat pins Node 24.16.0 in .nvmrc and builds on node:24.16.0-alpine,
  and every /docs/local/npm guide already states v24.16.0. The card was the
  only remaining place claiming v20.19+.
- LibreChat has no root postinstall, so `npm ci` installs workspace
  dependencies without building packages/data-provider, data-schemas, api,
  packages/client or the client bundle. `npm run backend` cannot start from
  that state. `npm run reinstall` (config/update.js -l -g) runs `npm ci`
  followed by `npm run frontend`, which is what the full guide instructs.

Only untranslated structural data changed, so no locale dictionary is
affected.

Reported via Discord docs feedback 1545085630760095786 (/docs/local).
…breChat-AI#751)

* fix(docs): send the Object Structure card and legacy /toolkit URLs to real pages

The Object Structure card on the librechat.yaml page linked to
/docs/configuration/librechat_yaml/object_structure, a nav-only folder with
no index page, so the one card promising the "complete field reference"
404'd. Point it at the Config Structure page the section actually opens
with, and redirect the folder URL there for anyone who typed or bookmarked
it.

The legacy /toolkit redirects pointed one dead spelling at another
(/toolkit/yaml_checker -> /toolkit/yaml-checker); neither exists since the
toolkit moved under /docs/toolkit. In-page links survive because
lib/localize-href.ts canonicalizes them at render time, so this only bit
direct hits, including the one absolute toolkit URL in the Linux guide
that skipped canonicalization for being external-shaped. Redirect targets
now match the canonical map in localize-href.ts.

Feedback: 1531982915729359019, 1491241561986564299

* docs(config): document the speechTab fields and defaultParamsEndpoint values

The speechTab section showed an example with eleven keys and explained
none of them. Add the field reference from the schema: accepted engine
values for STT and TTS, and the two settings whose meaning is not
guessable: decibelValue is a silence threshold in dB (-100 to -30,
default -45) and autoSendText is a delay in seconds where -1 disables
auto-send.

Neither speech page mentioned allowedAddresses, though speech.stt and
speech.tts both take one and every self-hosted example we ship
(host.docker.internal, localhost) is inside the private address space the
connect-time guard blocks.

defaultParamsEndpoint is z.string().default('custom'), not an enum, and
the page only showed 'google' as an example. The panel resolves it via
paramSettings[key] ?? [], so an unrecognized value passes validation and
renders an empty parameter panel instead of reporting an error. List the
keys that resolve and describe that failure mode.

Feedback: 1543536529195012169, 1506499310035140753

* docs(ollama): add troubleshooting and caption the stop-sequence screenshot

The Ollama reports were about diagnosis rather than the sample config. Add
the checks that resolve most failures: container-vs-host baseURL, Ollama's
default 127.0.0.1 bind, and the name-prefix rule behind model fetching:
models.ts reaches for /api/tags first only when the endpoint name starts
with "ollama". Also
note that a remote or hosted server differs only in baseURL and apiKey.

The stop-sequence screenshot had "image" as its alt text and no caption
saying which panel it shows.

Feedback: 1539423034283393146, 1529194857564995645, 1528452749685952575

* docs(features): answer recurring questions on banners, export, and search

Banner: update-banner does findOne() then findByIdAndUpdate, so there is
only ever one banner and running it again overwrites the previous message
and schedule. Two overlapping windows are therefore not possible, and
delete-banner is the only way to take one down early.

Import Conversations: the "Export your conversations" heading covered
exporting *from* ChatGPT and Claude, so readers looking for LibreChat's own
export found the wrong thing. Rename that section and document the real
export flow, its five formats, and the branch and option rules that vary
by format.

Message Search: say plainly that conversation search is keyword-based and
that semantic retrieval applies to uploaded files through the RAG API,
rather than leaving readers to infer it from "Meilisearch".

Transactions: the setting only controls whether records are written, which
is why enabling it does not make token counts appear anywhere. Point at
interface.contextUsage and contextCost for the display.

Feedback: 1494744632884596746, 1528752311281647727, 1508348821095059487,
1508345688273191073, 1522687279234289807

* docs: drop leftover social-media hashtag blocks

LibreChat-AI#699 removed the pasted video description from artifacts.mdx but the same
boilerplate survived on two other feature pages: a trailing hashtag line on
agents.mdx (plus the horizontal rule left orphaned above it) and on
code_interpreter.mdx. Both had already been machine-translated into every
locale.

Feedback: 1532228462868168886

* fix(docs): SAML_ISSUER is LibreChat's entity ID, not Auth0's

The Auth0 SAML guide told readers to copy Auth0's Issuer into SAML_ISSUER,
and its example set it to `urn:dev-xxxxx.us.auth0.com`. That is backwards.
samlStrategy.js:315 passes SAML_ISSUER as the strategy's `issuer`, which is
the entity ID LibreChat asserts about *itself* in outbound AuthnRequests and
must match the Audience configured on the Auth0 side. The identity
provider's own issuer belongs in SAML_IDP_ISSUER, used at
samlStrategy.js:185 to verify incoming assertions.

Following the page as written produced a mismatched audience on both sides.
Also states that LibreChat publishes no SP metadata document, which is what
the reporter went looking for, and fixes three typos on the lines touched.

Feedback: 1486774904136269884

* docs(endpoints): explain why a custom endpoint vanishes with no error

Seven reports say a provider never showed up after following the guide, and
the troubleshooting advice was to check the logs. That advice is misleading:
loadCustomEndpointsConfig (packages/api/src/endpoints/custom/config.ts:21-28)
filters out any endpoint missing `name`, `baseURL`, `apiKey` or `models`, or
whose `models` has neither `fetch: true` nor a non-empty `default`, and the
filter emits nothing at all. A typo or a mis-indented block therefore removes
the endpoint while the logs stay clean.

Rewrites the "Not Seeing Your Endpoint?" callout around inspecting the block
itself, notes that a duplicate name silently replaces the earlier entry, and
that a schema error anywhere in librechat.yaml stops the server rather than
disabling one section. Gives groq.mdx the enablement steps it never had:
its example uses `fetch: false`, so its `models.default` list is load-bearing
in exactly the way the filter punishes.

Also extends defaultParamsEndpoint with the four values that resolve during
schema lookup (parsers.ts:38-50) but map to no renderable parameter set.

Feedback: 1528641958187106465, 1477743384113447032, 1526344941800919159,
1477745639617073208, 1507234635573104813, 1481873299515506808

* docs: answer the installer, API-key, session, and S3 expiry questions

/docs/local: the desktop-installer callout added by LibreChat-AI#600 only ever landed on
/docs, and /docs/local is the page the "where's the Windows installer"
report was actually filed against. It rendered as a bare install-options
grid with nothing saying LibreChat is not a downloadable app.

pre_configured_ai/openai: `user_provided` was mentioned with no explanation
of what users then do. Documents the Set API Key gear in the endpoint menu,
the expiry choices (30m/2h/12h default/1d/7d/30d/never), that the key is
encrypted per user server-side, and the revoke path.

features/authentication: no mention of session length, so "I keep getting
logged out" had nowhere to land. Adds the SESSION_EXPIRY (15m) and
REFRESH_TOKEN_EXPIRY (7d) defaults, explains that the short token renews
silently, and states plainly that there is no anonymous mode.

cdn/s3: S3_REFRESH_EXPIRY_MS was the one env var the storage code reads that
the page never listed.

Feedback: 1496108363296018513, 1488860965666816060, 1500577570784149656,
1517360828762947625, 1482888861599399978

* docs(cdn): say what a file storage provider is actually used for

The Azure page described the service but never what LibreChat stores in it,
which was the reported complaint. Storage strategy is not a feature toggle:
it decides where avatars, chat uploads, image-generation output, and Code
Interpreter files all go. Names those consumers and the reason to move off
the default local disk, which does not survive container recreation and
cannot be shared across replicas.

Feedback: 1512086950859767868

* docs(speech): correct autoSendText units and autoTranscribeAudio behavior

autoSendText is seconds, not milliseconds, and -1 is what disables
auto-send; 0 sends immediately. autoTranscribeAudio controls continuous
listening (and silence detection on external engines), not transcription
of audio messages. The reference table and the STT/TTS guide disagreed
with each other and both disagreed with the client.

Also note that privately resolved cloud endpoints are not exempt from the
SSRF guard, and that browser TTS voices come from the OS rather than a
configured voice list.

* docs: address review feedback on endpoint, banner, and auth pages

- Drop the Groq enable-the-endpoint section; the custom endpoints guide
  already covers it.
- contextUsage draws the gauge and is on by default; contextCost only
  adds pricing and is off by default. Don't present both as required.
- An account is required to chat, but ALLOW_SHARED_LINKS_PUBLIC lets
  anonymous visitors read a shared conversation.
- defaultParamsEndpoint is filled in from provider when omitted, so
  'custom' is not the effective default for a provider-backed endpoint.
- Warn that OLLAMA_HOST=0.0.0.0 exposes an unauthenticated API on every
  interface, and explain that apiKey is only the Bearer fallback.
- Replace double hyphens used as pauses.

* docs: correct storage persistence, Ollama model fetch, and key entry paths

- Compose bind-mounts ./images and ./uploads to the host, so local file
  storage is not lost when the API container is recreated. Scope the
  warning to multi-instance and no-persistent-volume deployments.
- A renamed Ollama endpoint does not come back with an empty model list.
  The native /api/tags call is tried only for names starting with ollama,
  but any other name, or a failure, falls through to /v1/models, which
  Ollama serves at the documented /v1/ base URL.
- Auth0's Settings JSON needs an audience matching SAML_ISSUER, otherwise
  Auth0 asserts its default audience and login fails on a mismatch.
- Provider keys can also be set from Settings, Data controls, API keys,
  which is the only path when a model spec hides the endpoint menu.

* fix(docs): canonicalize the object_structure folder link for every locale

The next.config redirect only covers the unprefixed URL. Translated
index pages still carry the nav-only folder as the Object Structure card
target, and TrackedLink prefixes it with the active locale, so the card
stayed a 404 for all thirteen non-English readers.

Canonicalize the path in localize-href alongside the legacy /toolkit
aliases, which happens before locale prefixing and so fixes every locale
at render time. Verified against a production server: no locale emits
the bare folder href any more.

Also note that a refresh inherits the session's original expiry rather
than restarting it, so REFRESH_TOKEN_EXPIRY is measured from login.

* docs(auth): scope session expiry to LibreChat-issued refresh tokens

With OPENID_REUSE_TOKENS=true the refresh cookie holds the provider's
token, so the IdP's lifetime, rotation, and revocation policy end the
session and raising REFRESH_TOKEN_EXPIRY cannot extend it.

* docs(ollama): correct the stale 'fetching not supported' comments

The page's primary example already uses fetch: true, and models.ts has a
dedicated Ollama fetch path, so the two examples in the stop-sequence
callout contradicted the rest of the page. Say why the list is pinned
instead, and let the hosted-proxy example fetch, which is the point of
the /v1/models fallback described above it.
* docs: add AMD Lemonade custom endpoint provider

* docs: align Lemonade guide with other AI endpoints
…reChat-AI#757)

* docs: clarify that user_provided keys need no .env entry

The custom endpoints quick start offered `user_provided` as one of three
apiKey styles and then sent every reader into "Step 3. Set Environment
Variables", which reads as mandatory. A reader who picked `user_provided`
was told to do the one thing that option exists to avoid.

Scope Step 3 to the `${VARIABLE_NAME}` form and say so in the callout, so
each option states whether it needs an .env entry at all. Verified against
initializeCustom in packages/api/src/endpoints/custom/initialize.ts: a
`user_provided` endpoint reads the key from the per-user encrypted Key
record and never touches process.env.

Also list ANTHROPIC_API_KEY in the .env sample, which the example config
above references but the sample omitted, and note that an unresolved
`${VAR}` keeps the endpoint in the selector and only fails at send time
rather than dropping it.

Feedback: 1545680589888421981

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RtKgYeptrzc2kctgcyR8Mf

* docs: replace MCP marketing bullet with a verifiable capability

"Providing a growing ecosystem of dynamic, ready-to-use integrations" told
the reader nothing and was not accurate: LibreChat ships no built-in MCP
registry, marketplace or curated catalog, and users always supply their own
server config through librechat.yaml or the MCP Settings panel. Smithery is
an external site, not a bundled catalog.

Replace it with runtime server management, which the page already documents
at length under "Adding MCP Servers in the UI" and which is backed by
createMCPServerController and MCPServersRegistry.addServer in the app.

That bullet contradicted the blanket "any time you add or edit an MCP
server, you will need to restart LibreChat" two paragraphs below, so scope
that sentence to librechat.yaml servers. YAML servers load at boot with no
file watcher; servers saved through the panel are inspected and stored in
the DB tier during the request and need no restart.

Feedback: 1545680954620780568, 1545681058937307189

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RtKgYeptrzc2kctgcyR8Mf

* docs: scope the runtime-init and missing-variable claims

Two accuracy corrections from PR review on the previous two commits.

The MCP intro said servers added in the MCP Settings panel "are
initialized as soon as they are saved". That contradicts Step 3 of the
same page: a panel-created server that uses OAuth is registered on save
but shows as disconnected until the user runs the authenticate flow.
Saying it is initialized on save invites readers to skip that step, so
the sentence now claims only that the configuration takes effect without
a restart and points at the authentication step.

The custom endpoints page said a missing .env entry surfaces as
"Missing API Key for <endpoint>". That holds only when the unresolved
reference is the endpoint's apiKey. initializeCustom resolves apiKey and
baseURL separately and throws a distinct error for each, so name both
instead of presenting the apiKey failure as universal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwbrBkBq4fq9G8g3oRnh1j

* docs: base the Step 3 skip rule on every env reference

The skip condition told readers to jump past Step 3 whenever every
endpoint used `user_provided`, but `apiKey` is not the only field that
takes `${VARIABLE_NAME}`. resolveHeaders runs each header value through
processSingleValue, which calls extractEnvVariable, so a header such as
`X-Tenant: '${TENANT_ID}'` needs a .env entry even when no endpoint
reads a key from the environment.

Base the skip on whether the configuration contains any `${...}`
reference at all, and scope the two callout claims to the API key rather
than to Step 3 as a whole.

Also name the header failure mode, which is quieter than the other two:
RESOLVABLE_PLACEHOLDER_PATTERN only strips `{{...}}` forms, so an
unresolved `${VAR}` in a header reaches the provider as literal text
instead of raising a LibreChat error.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwbrBkBq4fq9G8g3oRnh1j

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…all hub (LibreChat-AI#758)

A reader on /de/docs/local reported that they wanted a Windows app. The
Local Installation hub renders three install cards and no prose, so
nothing on the page tells a reader that LibreChat is a self-hosted web
application rather than something you download and run natively.

/docs already carries this clarification (added in LibreChat-AI#600), but the install
hub is a separate entry point that readers reach directly from search and
from the sidebar, so that note never reaches them. The complaint arriving
again on /docs/local is evidence that one placement is not enough.

Adds a short callout that answers the question directly and points Windows
readers at Docker Desktop. The localhost URL is scoped to Docker and npm,
since the Helm chart deploys to a Kubernetes cluster and is reached through
cluster networking rather than a local address. Also widens the page
description so the expectation is set in search results.

Verified against the app source at origin/dev: LibreChat has no Electron,
Tauri, or other desktop packaging, and PORT defaults to 3080 in
.env.example.

Discord feedback ID: 1546161795104768073


Claude-Session: https://claude.ai/code/session_01UqsVMs6sqXvDj8KvRut897

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: use Vercel promotion events for cache purges

* fix: preserve cache purge rollback safety

* fix: read purge inputs from deployed source

* fix: constrain promoted commits to main

* fix: preserve cache purge promotion order

* fix: record cache promotions before purging

* fix: reconcile queued cache promotions

* fix: cover all production promotions

* fix: make automatic cache purges stateless

* docs: clarify automatic cache purge behavior
Document Scalattice as an OpenAI-compatible custom endpoint with live catalog fetch.
@vercel

vercel Bot commented Sep 9, 2026

Copy link
Copy Markdown

@romulushill is attempting to deploy a commit to the LibreChat's projects Team on Vercel.

A member of the Team first needs to authorize it.

@romulushill

Copy link
Copy Markdown
Author

Hey, rebased this onto main. Just a custom endpoint page, pretty small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants