LibreChat/packages/data-provider/specs
Danny Avila bce93f9c55
🎯 refactor: Infer Agents Endpoint for Model Specs Naming an Agent (#14889)
* 🎯 fix: Infer Agents Endpoint for Model Specs Naming an Agent

A model spec whose preset names an `agent_id` but omits `endpoint` was
unusable. `isModelSpecEndpointMatch` compares the request's endpoint to
`preset.endpoint` by strict equality, so an undefined endpoint matched
nothing and every request selecting the spec was rejected with a bare
`Model spec mismatch` — an error naming neither the spec nor the missing
field.

The selector had the matching half of the same gap: `handleSelectSpec`
read `preset.endpoint` directly, so it sent no endpoint and skipped
assigning `agent_id` to `model`. Fixing only the server would leave the
request malformed, so the resolution is shared between both.

- Add `resolveModelSpecEndpoint` to `librechat-data-provider`, inferring
  the agents endpoint when a preset names an agent and none is set. An
  explicit `endpoint` always wins, so configured specs are unaffected.
- Use it for endpoint matching and in the selector, so the menu and the
  request pipeline resolve a spec identically.

* 🔁 refactor: Materialize Inferred Spec Endpoints at Config Load

The review showed the lazy-resolver approach was unsound end to end:
config validation rejected an endpoint-less spec before the resolver
could ever run (`tPresetSchema` requires the `endpoint` key), and the
resolver was applied at 2 of ~8 read sites, leaving selection handlers,
startup presets, access filters, and provider-key reachability reading
the raw preset.

Materialize once at the boundary instead:

- `tModelSpecPresetSchema` now makes `endpoint` optional (`nullish`).
  This is barely a widening — `endpoint: null` already validated — and
  only for model-spec presets; `tPresetSchema` is untouched.
- `materializeModelSpecEndpoints` writes each spec's resolved endpoint
  back onto its preset. `createAppConfigService` applies it at both
  effective-config assembly points — YAML base load and DB-override
  merge — so admin-panel specs stored in override documents are covered.
  Identity-preserving, so cached configs see no new references when
  nothing needs filling in.
- Every consumer now reads complete specs; the client's lazy resolve in
  `handleSelectSpec` is reverted to a raw read. `getModelSpecPreset` and
  the two hand-rolled preset constructions resolve the endpoint
  explicitly, which the narrowed preset type now enforces at compile
  time for any `TPreset`-shaped destination.
- `isModelSpecEndpointMatch` keeps the resolver as request-time defense.

* 🩹 fix: Materialize Spec Endpoints Before the YAML Missing-Endpoint Guard

`processModelSpecs` warns and skips any spec whose preset lacks an
endpoint, and it runs inside `loadBaseConfig` — so the previous commit's
materialization received a YAML list from which the inferable spec had
already been dropped. Only DB-override specs (merged after the guard)
actually benefited.

- Materialize at the entry of `processModelSpecs`, so inference happens
  before the guard and YAML agent specs survive it. The guard keeps
  skipping genuinely endpoint-less specs. The `createAppConfigService`
  calls stay: the base-path one guards alternate `loadBaseConfig`
  implementations, the merged-path one covers override documents, and
  both are identity-preserving no-ops when specs are already complete.
- Constrain the widened schema: omitting `endpoint` is only legal when
  the preset names an `agent_id`. A preset with neither validated as a
  hard error before the key became optional, and silently accepting it
  would trade that startup-time error for a dead spec. An explicit
  `endpoint: null` (valid before this PR) keeps validating.

* 🩹 fix: Infer Only From Non-Empty Agent IDs, Never Over Explicit Null

Two edge cases in the inference contract:

- `agent_id: ''` (what a form-backed writer persists for an untouched
  field) passed the nullish checks, validating and materializing a spec
  that names no agent. Both the refinement and the resolver now require
  a non-empty id, so such config fails validation loudly instead of
  producing a selectable spec that cannot work.
- `endpoint: null` alongside an `agent_id` was treated as inferable,
  silently activating a spec that validated — and was skipped — before
  this PR. An explicit null is a statement, not an omission: the
  resolver now infers only when the key is absent, preserving prior
  behavior for previously valid configs.
2026-08-16 11:04:52 -04:00
..
actions.spec.ts fix: Bind Action Servers to Metadata Ports (#14575) 2026-08-02 13:41:31 -04:00
api-endpoints-subdir.spec.ts
api-endpoints.spec.ts 🔗 feat: Shared Conversation Badge and Stable Share Links (#14712) 2026-08-09 08:14:54 -04:00
azure.spec.ts
bedrock.spec.ts ✳️ feat: Claude Opus 5 Support (#14422) 2026-07-24 21:45:32 -04:00
config-schemas.spec.ts 🎯 refactor: Infer Agents Endpoint for Model Specs Naming an Agent (#14889) 2026-08-16 11:04:52 -04:00
filetypes.spec.ts 🧹 refactor: Tighten Config Schema Typing and Remove Deprecated Fields (#12452) 2026-03-29 01:10:57 -04:00
generate.spec.ts
headers-helpers.spec.ts 🍪 refactor: Refresh CloudFront Media Cookies (#13091) 2026-05-12 13:26:05 -04:00
mcp.spec.ts 🔐 fix: Resolve Env Variables in MCP OAuth URL Fields (#13573) 2026-06-07 21:39:44 -04:00
openapiSpecs.ts
parsers.spec.ts 🧭 feat: Mid-Run Steering and Queued Messages for Agent Runs (#14220) 2026-07-14 10:11:10 -04:00
parsers.timezone.spec.ts 🕰️ feat: Resolve Agent Prompt Time Variables in User's Timezone (#13815) 2026-06-18 08:39:56 -04:00
request-interceptor-subdir.spec.ts 🎯 fix: Narrow Public Share 401 Bypass to the Share Endpoint Only (#12905) 2026-06-20 13:57:21 -04:00
request-interceptor.spec.ts 🛟 fix: Keep File Uploads Alive With SSE Heartbeats (#14295) 2026-07-21 19:27:09 -04:00
utils.spec.ts 🧯 fix: Prevent Env-Variable Exfil. via Placeholder Injection (#12260) 2026-03-16 08:48:24 -04:00