LibreChat/packages/api
Danny Avila a01959b3d2
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
🛰️ fix: Cross-Replica Created Event Delivery (#12231)
* fix: emit created event from metadata on cross-replica subscribe

In multi-instance Redis deployments, the created event (which triggers
sidebar conversation creation) was lost when the SSE subscriber connected
to a different instance than the one generating. The event was only in
the generating instance's local earlyEventBuffer and the Redis pub/sub
message was already gone by the time the subscriber's channel was active.

When subscribing cross-replica (empty buffer, Redis mode, userMessage
already in job metadata), reconstruct and emit the created event
directly from stored metadata.

* test: add skipBufferReplay regression guard for cross-replica created event

Add test asserting the resume path (skipBufferReplay: true) does NOT
emit a created event on cross-replica subscribe — prevents the
duplication fix from PR #12225 from regressing. Add explanatory JSDoc
on the cross-replica fallback branch documenting which fields are
preserved from trackUserMessage() and why sender/isCreatedByUser
are hardcoded.

* refactor: replace as-unknown-as casts with discriminated ServerSentEvent union

Split ServerSentEvent into StreamEvent | CreatedEvent | FinalEvent so
event shapes are statically typed. Removes all as-unknown-as casts in
GenerationJobManager and test file; narrows with proper union members
where properties are accessed.

* fix: await trackUserMessage before PUBLISH for structural ordering

trackUserMessage was fire-and-forget — the HSET for userMessage could
theoretically race with the PUBLISH. Await it so the write commits
before the pub/sub fires, guaranteeing any cross-replica getJob() after
the pub/sub window always finds userMessage in Redis. No-op for
non-created events (early return before any async work).

* refactor: type CreatedEvent.message explicitly, fix JSDoc and import

Give CreatedEvent.message its full known shape instead of
Record<string, unknown>. Update sendEvent JSDoc to reflect the
discriminated union. Use barrel import in test file.

* refactor: type FinalEvent fields with explicit message and conversation shapes

Replace Record<string, unknown> on requestMessage, responseMessage,
conversation, and runMessages with FinalMessageFields and a typed
conversation shape. Captures the known field set used by all final
event constructors (abort handler in GenerationJobManager and normal
completion in request.js) while allowing extension via index signature
for fields contributed by the full TMessage/TConversation schemas.

* refactor: narrow trackUserMessage with discriminated union, disambiguate error fields

Use 'created' in event to narrow ServerSentEvent to CreatedEvent,
eliminating all Record<string, unknown> casts and manual field
assertions. Add JSDoc to the two distinct error fields on
FinalMessageFields and FinalEvent to prevent confusion.

* fix: update cross-replica test to expect created event from metadata

The cross-replica subscribe fallback now correctly emits a created
event reconstructed from persisted metadata when userMessage exists
in the Redis job hash. Replica B receives 4 events (created + 3
deltas) instead of 3.
2026-03-15 11:11:10 -04:00
..
src 🛰️ fix: Cross-Replica Created Event Delivery (#12231) 2026-03-15 11:11:10 -04:00
.gitignore 🧠 feat: User Memories for Conversational Context (#7760) 2025-06-07 18:52:22 -04:00
babel.config.cjs 🧠 feat: User Memories for Conversational Context (#7760) 2025-06-07 18:52:22 -04:00
jest.config.mjs 🛂 fix: MCP OAuth Race Conditions, CSRF Fallback, and Token Expiry Handling (#12171) 2026-03-10 21:15:01 -04:00
package.json 📦 chore: Bump NPM Audit Packages (#12227) 2026-03-14 03:36:03 -04:00
rollup.config.js 🔄 refactor: Migrate Cache Logic to TypeScript (#9771) 2025-10-02 09:33:58 -04:00
tsconfig-paths-bootstrap.mjs 🧠 feat: User Memories for Conversational Context (#7760) 2025-06-07 18:52:22 -04:00
tsconfig.build.json 🧑‍💻 refactor: Secure Field Selection for 2FA & API Build Sourcemap (#9087) 2025-08-15 18:55:49 -04:00
tsconfig.json 🌊 feat: Resumable LLM Streams with Horizontal Scaling (#10926) 2025-12-19 12:14:19 -05:00
tsconfig.spec.json 🧠 feat: User Memories for Conversational Context (#7760) 2025-06-07 18:52:22 -04:00