LibreChat/packages/api/src/utils
Danny Avila 2350ebb24a
📨 feat: Custom Headers on Built-in Provider Endpoints (#13742)
* 📨 feat: Custom Headers on Built-in Provider Endpoints

Add a `headers` config option to the built-in `openAI`, `anthropic`, and
`google` endpoints (incl. Anthropic/Google Vertex), mirroring the custom
endpoint header mechanism. Values support the same placeholder resolution
(env vars, `{{LIBRECHAT_USER_*}}`, `{{LIBRECHAT_BODY_CONVERSATIONID}}`) and
are resolved at request time so dynamic values like conversationId resolve
against the live request — without losing provider-native request shaping.

Closes #13082. Covers #13713: forwarding conversationId to a reverse proxy
is now `X-Conversation-Id: '{{LIBRECHAT_BODY_CONVERSATIONID}}'` — an unknown
header is ignored by the native Anthropic API, so no 400 and no metadata
gating needed.

- Schema: `headers` on `baseEndpointSchema` (openAI/google/anthropic/all).
- New `mergeHeaders`/`resolveConfigHeaders` utils centralize the per-provider
  header locations (`configuration.defaultHeaders`, Anthropic
  `clientOptions.defaultHeaders`, Google `customHeaders`); provider-managed
  headers (auth, `anthropic-beta`) always win on collision.
- Each initializer threads configured headers (endpoint over `all`) into the
  right place; request-time resolution runs across all locations in the main
  and title flows.

* 🩹 fix: Cast endpoints.all to TEndpoint for headers DeepPartial widening

Adding `headers` (a Record) to `baseEndpointSchema` makes `DeepPartial<TCustomConfig>`
widen its value type to `string | undefined`, which is not assignable to the
concrete `TEndpoint['headers']: Record<string, string>` at the `loadedEndpoints.all`
assignment. Cast at the assignment site, mirroring the existing
`anthropicConfig as TAnthropicEndpoint` cast in the same function.

* 🛡️ fix: Harden built-in endpoint custom headers (Codex review)

Address Codex P2 findings on the custom-headers feature:

- Anthropic title requests: `omitTitleOptions` strips the `clientOptions`
  carrier, which dropped its `defaultHeaders`. Preserve just the header carrier
  so gateway/reverse-proxy metadata still reaches title generation.
- mergeHeaders: match header names case-insensitively so an override (e.g. a
  provider-managed `Authorization`/`anthropic-beta`) replaces/uniones a
  case-variant from the base instead of emitting two names a client may collapse.
- OpenAI: withhold admin-configured headers when the user supplies the base URL
  (`user_provided`), since values may carry `${SECRET}`/token placeholders that
  must not reach a user-controlled endpoint — mirrors the custom-endpoint guard.
- Azure: honor global `endpoints.all` headers (same OpenAI carrier) while keeping
  Azure-managed `api-key`/version headers authoritative.

Adds tests for each.

* 🔐 fix: Resolve-once + provider-managed header safety (Codex review round 2)

Address Codex P2 findings:

- Azure: keep global `endpoints.all` headers unresolved at init and let
  request-time `resolveConfigHeaders` resolve them once, avoiding a
  second-order env expansion of already-substituted user values.
- Google: `resolveConfigHeaders` no longer template-resolves the
  provider-managed `Authorization` header (built from a possibly user-provided
  key), so a user key like `${ENV}` can't leak server environment values.
- Model fetches: thread configured headers (endpoint over `all`) + user object
  through `getOpenAIModels`/`getAnthropicModels` → `fetchModels`, so a
  gateway-fronted built-in provider receives the header on `/models` too. Fixed
  `fetchModels` to merge custom headers for Anthropic instead of overwriting
  them (managed `x-api-key`/version still win).

Adds/updates tests for each.

* 🧯 fix: Header provenance, memory/title coverage, idempotency (Codex round 3)

Address Codex P2 findings, including two regressions from the prior round:

- Google auth (findings 6 & 8): move native Google header resolution to init
  (`initializeGoogle`), resolving admin templates BEFORE the key-derived auth
  header is built. resolveConfigHeaders no longer touches Google `customHeaders`,
  so admin `Authorization` templates resolve again (fixes the round-2 regression)
  while the SDK auth header (possibly a user-provided key) is never env-expanded.
- Memory runs: memory extraction now calls `resolveConfigHeaders`, so native
  Anthropic (and OpenAI) headers resolve for memory requests too.
- Vertex titles: restore the ORIGINAL `clientOptions` object reference (not a
  copy) when preserving headers across `omitTitleOptions`, so the Vertex
  `createClient` closure and the resolved headers stay on the same object.
- Reuse: `resolveConfigHeaders` is now idempotent (resolve-once per header map),
  preventing a second pass from env-expanding values already substituted with
  user/body data when an agent object flows through buildAgentInput twice.

Adds/updates tests for each.
2026-06-14 17:02:04 -04:00
..
__tests__ 📡 feat: Support Unauthenticated SMTP Relays (#12322) 2026-03-20 13:07:39 -04:00
axios.spec.ts 👁️ feat: Azure Mistral OCR Strategy (#7888) 2025-06-13 15:14:57 -04:00
axios.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
azure.spec.ts
azure.ts 🎙️ fix: Azure OpenAI Speech-to-Text 400 Bad Request Error (#10355) 2025-11-05 10:27:34 -05:00
code.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
common.spec.ts
common.ts 📦 refactor: Consolidate DB models, encapsulating Mongoose usage in data-schemas (#11830) 2026-03-21 14:28:53 -04:00
content.spec.ts 🧬 chore: Align LibreChat With Agents LangChain Upgrade (#12922) 2026-05-03 12:46:01 -04:00
content.ts 🔧 fix: Await MCP Instructions and Filter Malformed Tool Calls (#10485) 2025-11-13 14:17:47 -05:00
email.ts 📡 feat: Support Unauthenticated SMTP Relays (#12322) 2026-03-20 13:07:39 -04:00
env.spec.ts 🗝️ fix: Resolve MCP Runtime User and Request Placeholders (#13626) 2026-06-09 18:52:57 -04:00
env.ts 🗝️ fix: Resolve MCP Runtime User and Request Placeholders (#13626) 2026-06-09 18:52:57 -04:00
events.ts 🛰️ fix: Cross-Replica Created Event Delivery (#12231) 2026-03-15 11:11:10 -04:00
files.spec.ts 🌐 fix: Preserve Unicode Filenames (#12977) 2026-05-06 14:57:38 -04:00
files.ts 🔐 feat: Add Signed CloudFront File Downloads (#12970) 2026-05-06 19:48:30 -04:00
generators.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
graph.spec.ts 🔬 ci: Add TypeScript Type Checks to Backend Workflow and Fix All Type Errors (#12451) 2026-03-28 21:06:39 -04:00
graph.ts 🗝️ fix: Resolve MCP Runtime User and Request Placeholders (#13626) 2026-06-09 18:52:57 -04:00
headers.spec.ts 📨 feat: Custom Headers on Built-in Provider Endpoints (#13742) 2026-06-14 17:02:04 -04:00
headers.ts 📨 feat: Custom Headers on Built-in Provider Endpoints (#13742) 2026-06-14 17:02:04 -04:00
http.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
import.ts 📏 refactor: Add File Size Limits to Conversation Imports (#12221) 2026-03-14 03:06:29 -04:00
index.ts 📨 feat: Custom Headers on Built-in Provider Endpoints (#13742) 2026-06-14 17:02:04 -04:00
key.test.ts 📂 refactor: File Read Operations (#9747) 2025-09-20 10:17:24 -04:00
key.ts 🧵 refactor: Migrate Endpoint Initialization to TypeScript (#10794) 2025-12-11 16:37:16 -05:00
latex.spec.ts 🔢 fix: Unescape LaTeX Numbers in Artifact Content Edit (#10476) 2025-11-13 08:19:19 -05:00
latex.ts 🔢 fix: Unescape LaTeX Numbers in Artifact Content Edit (#10476) 2025-11-13 08:19:19 -05:00
llm.test.ts 📎 feat: Upload as Text Support for Plaintext, STT, RAG, and Token Limits (#8868) 2025-08-27 03:44:39 -04:00
llm.ts 📎 feat: Upload as Text Support for Plaintext, STT, RAG, and Token Limits (#8868) 2025-08-27 03:44:39 -04:00
math.integration.spec.ts 🧮 refactor: Replace Eval with Safe Math Expression Parser (#11098) 2025-12-25 12:25:41 -05:00
math.spec.ts 🧮 refactor: Replace Eval with Safe Math Expression Parser (#11098) 2025-12-25 12:25:41 -05:00
math.ts 🧮 refactor: Replace Eval with Safe Math Expression Parser (#11098) 2025-12-25 12:25:41 -05:00
memory.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
message.spec.ts 🧵 fix: Reject Preliminary Parent Follow-Ups (#13619) 2026-06-09 12:06:51 -04:00
message.ts 🧵 fix: Reject Preliminary Parent Follow-Ups (#13619) 2026-06-09 12:06:51 -04:00
oidc.spec.ts 🔬 ci: Add TypeScript Type Checks to Backend Workflow and Fix All Type Errors (#12451) 2026-03-28 21:06:39 -04:00
oidc.ts 🔬 ci: Add TypeScript Type Checks to Backend Workflow and Fix All Type Errors (#12451) 2026-03-28 21:06:39 -04:00
openid.ts 🔍 refactor: OpenID Fetch Handling and Logging (#7790) 2025-06-09 11:27:23 -04:00
path.spec.ts 🧭 fix: Add Base Path Support for Login/Register and Image Paths (#10116) 2025-11-21 11:25:14 -05:00
path.ts 🧭 fix: Add Base Path Support for Login/Register and Image Paths (#10116) 2025-11-21 11:25:14 -05:00
ports.spec.ts 🪤 fix: Avoid express-rate-limit v8 ERR_ERL_KEY_GEN_IPV6 False Positive (#12333) 2026-03-20 12:32:55 -04:00
ports.ts 🪤 fix: Avoid express-rate-limit v8 ERR_ERL_KEY_GEN_IPV6 False Positive (#12333) 2026-03-20 12:32:55 -04:00
promise.spec.ts refactor: Bound Concurrent Office-HTML Rendering for Code Artifacts (#12951) 2026-05-05 08:53:21 -04:00
promise.ts refactor: Bound Concurrent Office-HTML Rendering for Code Artifacts (#12951) 2026-05-05 08:53:21 -04:00
proxy.spec.ts 🌐 fix: Centralize Outbound Proxy Handling (#13726) 2026-06-14 10:47:49 -04:00
proxy.ts 🌐 fix: Centralize Outbound Proxy Handling (#13726) 2026-06-14 10:47:49 -04:00
sanitizeTitle.spec.ts ✂️ fix: Unicode-Safe Title Truncation and Shared View Layout Polish (#12003) 2026-03-01 16:44:57 -05:00
sanitizeTitle.ts ✂️ fix: Unicode-Safe Title Truncation and Shared View Layout Polish (#12003) 2026-03-01 16:44:57 -05:00
text.spec.ts 🧠 fix: Bound Memory Agent Input (#13606) 2026-06-09 14:38:21 -04:00
text.ts 🧠 fix: Bound Memory Agent Input (#13606) 2026-06-09 14:38:21 -04:00
tokenizer.spec.ts refactor: Replace tiktoken with ai-tokenizer (#12175) 2026-03-10 23:14:52 -04:00
tokenizer.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00
tokenMap.ts 🧬 chore: Align LibreChat With Agents LangChain Upgrade (#12922) 2026-05-03 12:46:01 -04:00
tokens.spec.ts 📊 feat: Real-Time Context Window & Token Usage Tracking (#13670) 2026-06-13 19:38:28 -04:00
tokens.ts 📊 feat: Real-Time Context Window & Token Usage Tracking (#13670) 2026-06-13 19:38:28 -04:00
tracing.ts 🪣 fix: Prevent Memory Retention from AsyncLocalStorage Context Propagation (#11942) 2026-02-25 17:41:23 -05:00
url.spec.ts 🧵 refactor: Migrate Endpoint Initialization to TypeScript (#10794) 2025-12-11 16:37:16 -05:00
url.ts 🧵 refactor: Migrate Endpoint Initialization to TypeScript (#10794) 2025-12-11 16:37:16 -05:00
yaml.ts ️ refactor: Migrate @librechat/api build to tsdown (#13595) 2026-06-08 10:54:48 -04:00