LibreChat/api/server/controllers/agents/__tests__
Danny Avila 770238f22b
🔣 refactor: Replace Mongo Filters With Typed Criteria (#15580)
* ♻️ refactor: Take Typed Criteria, Not Mongo Filters, for Actions and Assistants

`createActionMethods` and `createAssistantMethods` accepted `FilterQuery<T>`,
putting Mongoose's query language in the package's public surface: every caller
wrote raw Mongo, and no engine other than Mongo could satisfy the signatures.

Both now take domain criteria — `ActionQuery` and `AssistantQuery` — naming
concepts rather than stored fields, with an array meaning "any of these". A
per-domain field map translates them, so `FilterQuery` survives only inside the
two translators.

`buildFilter` throws on a criterion the field map does not cover. Callers in
`api/` are JavaScript and get no compile-time checking, and the server sets
`strictQuery`, under which a silently dropped criterion widens the filter
instead of narrowing it — an unscoped `findOne` returns an arbitrary document
rather than none. Failing closed is the only safe default.

`AssistantQuery.avatarFilepath` covers the avatar-authorization lookup, which
queries a nested path no plain field name reaches.

No behaviour change: every migrated call site produces the same filter as before.

* 🧪 test: Update Avatar Authorization Assertion to Typed Criteria

`validateImages.spec.js` asserted the old `{ 'avatar.filepath': { $in: [...] } }`
call shape for `getAssistant`. The earlier sweep matched on `action_id`,
`agent_id` and `assistant_id`, none of which appear in a dotted avatar path, so
this one assertion was missed.

The `getAgent` assertions in the same file keep the filter shape — that method
still takes a `FilterQuery`.

* 🔒 fix: Reject Unknown Criteria Before Omitting Undefined Ones

`buildFilter` skipped a criterion whose value was `undefined` before checking it
against the field map, so a JavaScript caller misspelling a key that happened to
carry `undefined` — `deleteActions({ agent_id: maybeId })` — produced `{}` and
reached `deleteMany` unscoped. That is the exact failure the guard exists to
prevent, defeated by the order of the two checks.

Validate every key first, then apply the undefined-omission rule. The lookup is
an own-property check so inherited names cannot resolve through the field map's
prototype: `{ toString: 'x' }` previously found `Function.prototype.toString`,
passed the truthiness test, and wrote a garbage filter key instead of throwing.

A recognized criterion left `undefined` is still omitted, so optional parameters
keep working.

* 🔒 fix: Reject Query Fragments as Criteria and Keep the Translator Internal

Three review findings on the criteria translator, all of the same shape: the
guard was narrower than the surface it protects.

Criterion values are now validated as scalars or lists of scalars. `matchAny`
copied any non-array through unchanged, so a JavaScript caller could pass
`{ agentId: { $ne: null } }` and have the operator land verbatim in the filter
— the fail-open case the field map exists to close. `null` is rejected too; it
would have matched documents missing the field entirely.

`matchAny`, `buildFilter` and `FieldMap` are no longer re-exported from the
package barrel. They emit Mongo, and shipping them as public API undercut the
point of the change; they were reachable as `require('@librechat/data-schemas')
.buildFilter`. `OneOrMany` moves to `types/query` because the domain query types
reference it and it names no engine — which also drops the `types` -> `utils`
import.

`loadActionSets` names `ActionQuery` through `import()` so the JSDoc type
actually resolves.
2026-09-04 11:54:21 -04:00
..
askUserQuestion.e2e.spec.js ⚡ feat: Reliable Interrupt & Steer Escalation and Recovery (#14558) 2026-07-31 20:07:56 -04:00
callbacks.spec.js 🧊 feat: Persist Context Fading Tier Across Agent Runs (#15505) 2026-09-02 20:29:43 -04:00
client.contextMetadata.spec.js
client.eventActorPause.spec.js 🤖 feat: make Event Actor HITL durable (#15305) 2026-08-28 08:05:11 -04:00
client.memory.spec.js
client.steerWiring.spec.js 🍵 feat: Continue Late Steers in Warm Agent Runs (#15357) 2026-08-30 11:54:17 -04:00
client.subagentUsage.spec.js 🧵 feat: Persist View-Only Subagent Threads (#14957) 2026-08-18 07:41:42 -04:00
client.transactions.spec.js 🧾 fix: Honor Disabled Transactions on the Token-Count Fallback Path (#14774) 2026-08-12 22:31:13 -04:00
hitlCheckpoint.e2e.spec.js ⚡ feat: Reliable Interrupt & Steer Escalation and Recovery (#14558) 2026-07-31 20:07:56 -04:00
jobReplacement.spec.js
modelEndHandler.spec.js 🧾 fix: Report Complete Agents API Usage (#15127) 2026-08-23 02:37:09 -04:00
openai.spec.js 🪪 feat: Propagate Tenant to Agent Model Headers (#15521) 2026-09-02 13:25:38 -04:00
protocol.spec.js 🛫 refactor: Promote Generation Protocol V2 Automatically (#15324) 2026-08-28 17:17:09 -04:00
request.partialDisconnect.spec.js 🧊 feat: Persist Context Fading Tier Across Agent Runs (#15505) 2026-09-02 20:29:43 -04:00
request.resumeMetadata.spec.js 🧊 feat: Persist Context Fading Tier Across Agent Runs (#15505) 2026-09-02 20:29:43 -04:00
responses.unit.spec.js 🪪 feat: Propagate Tenant to Agent Model Headers (#15521) 2026-09-02 13:25:38 -04:00
resume.spec.js 🔣 refactor: Replace Mongo Filters With Typed Criteria (#15580) 2026-09-04 11:54:21 -04:00
steer.spec.js 🛫 refactor: Promote Generation Protocol V2 Automatically (#15324) 2026-08-28 17:17:09 -04:00
usageEvents.integration.spec.js
usageEvents.live.spec.js
v1.duplicate-actions.spec.js 🛞 feat: Manage Personal Code Environment Lifecycles (#15369) 2026-09-01 21:10:05 -04:00
v1.spec.js 🔣 refactor: Replace Mongo Filters With Typed Criteria (#15580) 2026-09-04 11:54:21 -04:00