Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
94fed5b
🥡 fix: Delete Storage and Embeddings With Owned Agent Files (#16007)
lia-by-librechat[bot] Sep 17, 2026
db674ed
🔓 fix: Stop Code Outputs and Tool-Routed Spreadsheets From Locking Th…
danny-avila Sep 18, 2026
02efb1d
🚥 test: Hold Group Cache Reads Until Concurrent Callers Arrive (#16059)
lia-by-librechat[bot] Sep 18, 2026
03f182f
🔑 fix: Ask for MCP Sign-In When a Server Rejects Refreshed Tokens (#1…
danny-avila Sep 18, 2026
5c72d41
📱 fix: Fit the Tool Library and Skills Pickers to Small Screens (#16067)
berry-13 Sep 18, 2026
79d1cbb
🪶 perf: Cut the Mount Cost of Finished Agent Messages (#16057)
danny-avila Sep 18, 2026
c7665ab
🗾 fix: Route Cross-Region Attachments Through CloudFront (#16082)
upman Sep 18, 2026
038903a
📱 fix: Open Sign-In and External Links From iOS Home-Screen Apps (#16…
danny-avila Sep 19, 2026
c821638
🌓 refactor: Scrim OGDialog With the Overlay Theme Role (#16068)
berry-13 Sep 19, 2026
c0affed
🎟️ fix: Preserve BYOM Tool Calls Through Capacity Windows (#16060)
danny-avila Sep 19, 2026
7ceafeb
📤 fix(langfuse): support documented media upload types (#16079)
upman Sep 19, 2026
84aa045
📋 chore: Restructure Pull Request Template (#16094)
berry-13 Sep 19, 2026
9acf9f0
🫗 fix: Roll Back Incomplete Skill Archive Imports (#16052)
lia-by-librechat[bot] Sep 19, 2026
2f67471
🚐 perf: Enable Redis Stream Coalescing by Default (#16093)
lia-by-librechat[bot] Sep 19, 2026
1080f90
🎱 fix: Stop Sealing a Code Environment Decision a Chat Never Made (#1…
lia-by-librechat[bot] Sep 19, 2026
61d034c
📄 fix: Send Textual Documents to Claude Through Gateways as Text (#16…
mihidumh Sep 19, 2026
13c74c9
⛽ feat: Negotiate Background Command Timeouts (#16100)
danny-avila Sep 19, 2026
864c68e
🥾 fix: Define Code Execution Persistence Boundaries (#16099)
danny-avila Sep 19, 2026
aacf1de
🗂️ fix: Keep a Running Attachment Chat in the Sidebar (#16104)
danny-avila Sep 19, 2026
f80f0be
🔑 fix: Stringify Ban Cache Keys When Redis Is Off (#16039)
gokay-ai Sep 19, 2026
fa1e470
🗣️ feat: Trace Viewer Roles, Agent Identity and Tool Rounds (#16098)
danny-avila Sep 19, 2026
a35745b
💬 feat: Read a Model Call as a Conversation in the Trace Viewer (#16103)
danny-avila Sep 19, 2026
5d2fa85
📬 fix: Deliver Same-Turn Background Results (#16097)
danny-avila Sep 19, 2026
8a3ab43
📬 fix: Persist Background Results Before Parent Rows (#16101)
danny-avila Sep 20, 2026
36efc7b
🧺 fix: Bound Background Completion Batches (#16102)
danny-avila Sep 20, 2026
2df937d
🌳 feat: Isolate Attached Workspaces by Conversation (#16107)
danny-avila Sep 20, 2026
ba44443
📒 ci: Upload Per-Test Jest Results From Review Workflows (#16110)
danny-avila Sep 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -1232,11 +1232,13 @@ HELP_AND_FAQ_URL=https://librechat.ai
# SCHEDULES_DISABLED=true

# Coalesce streamed model/tool-argument deltas into windowed Redis publications (ms).
# Unset or 0 (default) publishes per delta. 25 is recommended: it batches the publish
# EVAL and the durable append across the window (fewer Redis round trips and lower
# Redis CPU at high token rates) at the cost of up to one window of added delivery
# latency. Enable only after EVERY replica runs a build with batch-frame support;
# older subscribers drop coalesced frames. Values are capped at 1000.
# Defaults to 25ms when unset; explicit 0 publishes per delta. Batches both publish
# and durable append operations (fewer Redis round trips and repeated guard/TTL work at high
# token rates), adding up to one window of buffering latency and crash-loss exposure
# for unflushed deltas. In-memory streams are unchanged. Values are capped at 1000.
# Batched publications retain individual chunk frames for older subscribers; Pub/Sub
# message count is unchanged. Incoming chunk_batch frames remain supported for existing
# opt-in producers. See UPGRADING.md for compatibility guidance.
# Keep the window <= the stream-smoothing cadence (`streamRate`, default 25ms):
# each smoothing tick emits its pieces in one burst, so a tick-sized window
# captures exactly one batch per tick; a larger window re-batches the paced
Expand Down
164 changes: 108 additions & 56 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
# Pull Request Template
# Pull Request

⚠️ Before Submitting a PR, Please Review:
- Please ensure that you have thoroughly read and understood the [Contributing Docs](https://github.com/danny-avila/LibreChat/blob/main/.github/CONTRIBUTING.md) before submitting your Pull Request.

⚠️ Documentation Updates Notice:
- Kindly note that documentation updates are managed in this repository: [librechat.ai](https://github.com/LibreChat-AI/librechat.ai)
> Before submitting, please review the [Contributing Guide](https://github.com/danny-avila/LibreChat/blob/main/.github/CONTRIBUTING.md).
>
> Documentation changes belong in the [LibreChat documentation repository](https://github.com/LibreChat-AI/librechat.ai).

## Summary

<!--
Say what breaks or is missing today, what triggers it, and how it behaves after this
change. Link the issue with `Fixes #N`, and list any dependency your change needs.
Two or three sentences is usually enough:

"Pasting an image while the composer had focus left Send disabled until the user
clicked back into the textarea: the upload dialog took focus and never returned it.
Focus now returns to the composer as soon as the attachment mounts."

Describe the code as it stands. A reader who has not followed the branch has no
context for what earlier commits tried or what a review round changed. Naming the
merged pull request that caused the bug is different — that is history the reader
needs.
Briefly explain:
- What problem or limitation exists today?
- What triggers it (input, state, or configuration)?
- What does this PR change?
- What is the resulting behavior?

Keep this focused on the final state of the code rather than the history of the
branch or previous review iterations. Naming the merged pull request that
introduced a regression is the exception: that is history the reader needs.

Link related issues, and name any dependency this change needs:
Fixes #123
Related to #123
Depends on danny-avila/agents#123
-->

## How it works

<!--
Optional. Delete this section when the summary already explains the change.
Optional. Remove this section if the implementation is already obvious from the
summary and diff.

Pick one or two views that make the change reviewable, and put a sentence beside
each. These show the format, not a required implementation pattern — replace them
with real names from your change. Do not paste the whole diff or list every file
you touched.
Explain the mechanism reviewers need to understand. Pick one or two of the views
below, whichever make the change reviewable, and put a sentence beside each rather
than describing every changed file. Show a whole block instead of a diff when most
of it is new, or when the omitted context would hide execution order or ownership.

The mechanism, as a focused diff, when the surrounding shape already exists:
Focused diff:

```diff
-const parts = content.filter(isText);
-const files = content.filter(isFile);
+const { parts, files } = splitContent(content);
```

Runtime order, as a call tree, keeping only the calls that carry the change:
Runtime flow:

```text
submitMessage
Expand All @@ -50,16 +51,16 @@ submitMessage
setSubmission # opens the SSE stream
```

Ownership, as a shallow file tree, for a new module or a broad refactor:
Ownership:

```text
packages/api/src/agents/
├── run.ts # builds the run and its callbacks
├── run.ts # builds the run and callbacks
├── tools.ts # resolves tools for the request
└── client.ts # streams provider output back to the route
└── client.ts # streams provider output
```

Client/server or cross-service flow, as Mermaid:
Cross-service flow:

```mermaid
sequenceDiagram
Expand All @@ -72,41 +73,92 @@ sequenceDiagram
API->>Client: SSE events
```

Editing this file: keep the arrows in the example above solid (`->>`). A dashed
Mermaid arrow spells the comment terminator, so it would close this comment early
and spill the rest of the guidance into every description. Your own diagram sits
outside the comment, where dashed arrows are fine.

Show a whole block instead of a diff when most of it is new, or when the omitted
context would hide execution order or ownership.
Keep the arrows in this example solid (`->>`). A dashed Mermaid arrow spells the
HTML comment terminator, so it would close this block early and spill the rest of
the guidance into every description. Diagrams you write outside this comment can
use dashed arrows freely.
-->

## Change Type
## Type of change

Please delete any irrelevant options.
<!-- Select all that apply. -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Translation update
* [ ] Bug fix
* [ ] Feature
* [ ] Refactor
* [ ] Performance improvement
* [ ] Breaking change
* [ ] Documentation
* [ ] Translation
* [ ] Tests / tooling / CI

## Testing

Please describe your test process and include instructions so that we can reproduce your test. If there are any important variables for your testing configuration, list them here.
<!--
Describe how you verified the change.

Include only the configuration that matters for reproducing the test.

Example:

1. Start LibreChat with Agents enabled.
2. Create an agent using an Ollama endpoint.
3. Add the Ask User tool.
4. Send a message that triggers the tool.
5. Confirm the question is rendered and the conversation continues after answering.
-->

### **Test Configuration**:
**Tested environments/configuration:**

<!--
Examples:
- Browser:
- Provider/model:
- Database:
- Feature flags:
- OS:
-->

**Automated tests:**

<!--
Examples:
- `npm run test:client`
- `npm run test:api`
- Added tests in `foo.spec.ts`

Write "Not applicable" when appropriate.
-->

## Screenshots / recordings

<!--
For user-facing changes, include before/after screenshots or a short recording.
Remove this section when not applicable.
-->

## Risk / compatibility

<!--
Optional for small changes.

Call out anything reviewers should pay particular attention to, such as:
- migrations or schema changes
- API/configuration changes
- provider-specific behavior
- backwards compatibility
- performance implications
- security-sensitive behavior

Write "None" when there are no notable risks.
-->

## Checklist

Please delete any irrelevant options.

- [ ] My code adheres to this project's style guidelines
- [ ] I have performed a self-review of my own code
- [ ] I have commented in any complex areas of my code
- [ ] I have made pertinent documentation changes
- [ ] My changes do not introduce new warnings
- [ ] I have written tests demonstrating that my changes are effective or that my feature works
- [ ] Local unit tests pass with my changes
- [ ] Any changes dependent on mine have been merged and published in downstream modules.
- [ ] A pull request for updating the documentation has been submitted.
* [ ] I reviewed my own changes
* [ ] Relevant tests have been added or updated
* [ ] Existing relevant tests pass
* [ ] The change does not introduce new warnings or errors
* [ ] User-facing or complex behavior is documented where necessary
* [ ] Required dependency changes have been merged/published
* [ ] Required documentation PR: <!-- link or N/A -->
80 changes: 68 additions & 12 deletions .github/workflows/backend-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,9 @@ jobs:
- name: Run unit tests (shard ${{ matrix.shard }}/3)
env:
SELECTED: ${{ needs.codegraph_select.outputs.api_files }}
JEST_JSON: --json --outputFile=${{ github.workspace }}/jest-results/jest-results-api-${{ matrix.shard }}.json
run: |
mkdir -p "$GITHUB_WORKSPACE/jest-results"
cd api
# A selected path can be stale in exactly two ways at this checkout (Codex P2, #15145 r6):
# deleted on the branch — dropped, which matches full CI (the file runs nowhere) — or
Expand All @@ -448,14 +450,26 @@ jobs:
KEEP="${KEEP# }"
if [ -z "$KEEP" ]; then
echo "no selected test file exists at HEAD (stale selection); running FULL"
npm run test:ci -- --shard=${{ matrix.shard }}/3
npm run test:ci -- --shard=${{ matrix.shard }}/3 $JEST_JSON
else
echo "codegraph: $(echo $KEEP | wc -w) selected test files (safe mode)"
npm run test:ci -- --shard=${{ matrix.shard }}/3 --passWithNoTests --runTestsByPath $KEEP
npm run test:ci -- --shard=${{ matrix.shard }}/3 --passWithNoTests --runTestsByPath $KEEP $JEST_JSON
fi
else
npm run test:ci -- --shard=${{ matrix.shard }}/3
npm run test:ci -- --shard=${{ matrix.shard }}/3 $JEST_JSON
fi
# Per-test results keyed by head SHA (run.head_sha), for the codegraph test-evidence feed.
# Never part of the gate: it cannot fail the job, and a re-run overwrites its own artifact.
- name: Upload Jest results
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/upload-artifact@v6
with:
name: jest-results-api-${{ matrix.shard }}
path: jest-results/
retention-days: 7
if-no-files-found: ignore
overwrite: true

test-data-provider:
name: 'Tests: data-provider'
Expand Down Expand Up @@ -509,7 +523,9 @@ jobs:
- name: Run unit tests
env:
SELECTED: ${{ needs.codegraph_select.outputs.dataprovider_files }}
JEST_JSON: --json --outputFile=${{ github.workspace }}/jest-results/jest-results-data-provider.json
run: |
mkdir -p "$GITHUB_WORKSPACE/jest-results"
cd packages/data-provider
if [ -n "$SELECTED" ]; then
KEEP=""
Expand All @@ -519,14 +535,26 @@ jobs:
KEEP="${KEEP# }"
if [ -z "$KEEP" ]; then
echo "no selected test file exists at HEAD (stale selection); running FULL"
npm run test:ci
npm run test:ci -- $JEST_JSON
else
echo "codegraph: $(echo $KEEP | wc -w) selected test files (safe mode)"
npm run test:ci -- --passWithNoTests --runTestsByPath $KEEP
npm run test:ci -- --passWithNoTests --runTestsByPath $KEEP $JEST_JSON
fi
else
npm run test:ci
npm run test:ci -- $JEST_JSON
fi
# Per-test results keyed by head SHA (run.head_sha), for the codegraph test-evidence feed.
# Never part of the gate: it cannot fail the job, and a re-run overwrites its own artifact.
- name: Upload Jest results
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/upload-artifact@v6
with:
name: jest-results-data-provider
path: jest-results/
retention-days: 7
if-no-files-found: ignore
overwrite: true

test-data-schemas:
name: 'Tests: data-schemas'
Expand Down Expand Up @@ -586,7 +614,9 @@ jobs:
- name: Run unit tests
env:
SELECTED: ${{ needs.codegraph_select.outputs.dataschemas_files }}
JEST_JSON: --json --outputFile=${{ github.workspace }}/jest-results/jest-results-data-schemas.json
run: |
mkdir -p "$GITHUB_WORKSPACE/jest-results"
cd packages/data-schemas
if [ -n "$SELECTED" ]; then
KEEP=""
Expand All @@ -596,14 +626,26 @@ jobs:
KEEP="${KEEP# }"
if [ -z "$KEEP" ]; then
echo "no selected test file exists at HEAD (stale selection); running FULL"
npm run test:ci
npm run test:ci -- $JEST_JSON
else
echo "codegraph: $(echo $KEEP | wc -w) selected test files (safe mode)"
npm run test:ci -- --passWithNoTests --runTestsByPath $KEEP
npm run test:ci -- --passWithNoTests --runTestsByPath $KEEP $JEST_JSON
fi
else
npm run test:ci
npm run test:ci -- $JEST_JSON
fi
# Per-test results keyed by head SHA (run.head_sha), for the codegraph test-evidence feed.
# Never part of the gate: it cannot fail the job, and a re-run overwrites its own artifact.
- name: Upload Jest results
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/upload-artifact@v6
with:
name: jest-results-data-schemas
path: jest-results/
retention-days: 7
if-no-files-found: ignore
overwrite: true

test-packages-api:
name: 'Tests: @librechat/api (shard ${{ matrix.shard }}/4)'
Expand Down Expand Up @@ -677,7 +719,9 @@ jobs:
- name: Run unit tests (shard ${{ matrix.shard }}/4)
env:
SELECTED: ${{ needs.codegraph_select.outputs.pkgapi_files }}
JEST_JSON: --json --outputFile=${{ github.workspace }}/jest-results/jest-results-packages-api-${{ matrix.shard }}.json
run: |
mkdir -p "$GITHUB_WORKSPACE/jest-results"
cd packages/api
if [ -n "$SELECTED" ]; then
KEEP=""
Expand All @@ -687,11 +731,23 @@ jobs:
KEEP="${KEEP# }"
if [ -z "$KEEP" ]; then
echo "no selected test file exists at HEAD (stale selection); running FULL"
npm run test:ci -- --shard=${{ matrix.shard }}/4
npm run test:ci -- --shard=${{ matrix.shard }}/4 $JEST_JSON
else
echo "codegraph: $(echo $KEEP | wc -w) selected test files (safe mode)"
npm run test:ci -- --shard=${{ matrix.shard }}/4 --passWithNoTests --runTestsByPath $KEEP
npm run test:ci -- --shard=${{ matrix.shard }}/4 --passWithNoTests --runTestsByPath $KEEP $JEST_JSON
fi
else
npm run test:ci -- --shard=${{ matrix.shard }}/4
npm run test:ci -- --shard=${{ matrix.shard }}/4 $JEST_JSON
fi
# Per-test results keyed by head SHA (run.head_sha), for the codegraph test-evidence feed.
# Never part of the gate: it cannot fail the job, and a re-run overwrites its own artifact.
- name: Upload Jest results
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/upload-artifact@v6
with:
name: jest-results-packages-api-${{ matrix.shard }}
path: jest-results/
retention-days: 7
if-no-files-found: ignore
overwrite: true
Loading
Loading