Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d346e5a
🚰 fix: Record the Provider Drain When Shutdown Cuts a Generation Shor…
danny-avila Sep 3, 2026
458c473
📧 fix: Normalize Token Emails on Write, as Every Read Already Does (#…
danny-avila Sep 3, 2026
2d794a0
💓 fix: Detect Silently Dead Redis Sockets With Deadline-Bounded Heart…
danny-avila Sep 3, 2026
ac55b5f
🧼 fix: Clear Model Spec Fields on Configured Selections (#15544)
danny-avila Sep 3, 2026
849e9bb
🧳 fix: Carry Logical Endpoints Through Agent Runs (#15538)
danny-avila Sep 3, 2026
5f187d3
🧽 test: Restore the Admin Allowlist Override This Spec Leaks Into the…
danny-avila Sep 3, 2026
f0dfeed
🐝 fix: Keep Polling for Owed Agent Successors (#15537)
danny-avila Sep 3, 2026
04e4fd6
🏛️ feat: Establish Agent Management API Contract (#15545)
danny-avila Sep 3, 2026
aec2121
🔐 feat: Add M2M Authentication for Agent Management (#15555)
dustinhealy Sep 4, 2026
a6cf61a
🪵 feat: Add OpenTelemetry Logs Pipeline via Winston Bridge (#15565)
danny-avila Sep 4, 2026
2fe872d
👀 feat: Add Agent Management Read Endpoints (#15561)
dustinhealy Sep 4, 2026
bd31ecd
✨ feat: add morphing state icons across the client (#14697)
berry-13 Sep 4, 2026
1c2796b
📮 fix: Validate Invite Email Claims (#15542)
lailson Sep 4, 2026
32e8724
🏗️ fix: Wait Out Concurrent Index Builds on DocumentDB (#15563)
danny-avila Sep 4, 2026
a9ce3d2
⏱️ test: Size the Subagent Lease TTL Above Shard Jitter (#15568)
danny-avila Sep 4, 2026
fde46a6
🔙 refactor: Keep Pasted Text Return Action Visible (#15586)
danny-avila Sep 4, 2026
2ffa9ec
➕ feat: Add Agent Management Creation Endpoint (#15564)
dustinhealy Sep 4, 2026
374ed8d
🧶 fix: Render Solo Agent Groups as Sequential Content (#15574)
danny-avila Sep 4, 2026
78b320c
🗜️ fix: Bound Conversation Page Size (#15576)
danny-avila Sep 4, 2026
1754297
🛞 fix: Re-Exchange Rejected OBO Tokens (#15577)
danny-avila Sep 4, 2026
bd83da5
👓 fix: Match Pasted Text Focus Feedback (#15588)
danny-avila Sep 4, 2026
9a43362
🪤 chore: Scope Assistant Tool-Resource Lookups (#15579)
danny-avila Sep 4, 2026
ab0d74b
✏️ feat: Add Agent Management Update Endpoint (#15566)
dustinhealy Sep 4, 2026
b76b020
🔬 test: Make the Paste Action's Hover-Gate Guard Actually Guard (#15589)
danny-avila Sep 4, 2026
59ab013
🔎 fix: Report Measured Skill Catalog Truncation (#15590)
danny-avila Sep 4, 2026
30cd1c2
🔇 fix: Stop logging an absent `create_file` target as an error (#15591)
danny-avila Sep 4, 2026
6510908
🧬 fix: Carry Whole File Refs Through Sandbox Authoring (#15593)
danny-avila Sep 4, 2026
5840e2f
🪓 feat: Add Tenant-Scoped Agent Deletion (#15573)
dustinhealy Sep 4, 2026
b7fd4ba
👓 feat: Read Attached Workspace Files (#15524)
danny-avila Sep 4, 2026
9a64e85
🕯️ feat: Search Text in Attached Workspaces (#15525)
danny-avila Sep 4, 2026
c00acb3
🌌 feat: Add GPT-6 Astra Support (#15567)
danny-avila Sep 4, 2026
ee0a51a
🪵 fix: Log Code API Auth Header Failures With Request Context (#15592)
danny-avila Sep 4, 2026
22a83bd
🥣 fix: Apply Agent Shaping to Built-In Summarizers (#15599)
danny-avila Sep 4, 2026
10c5c91
🎨 feat: Theme-Adaptive SVG Support for Custom MCP and Group Icons (#1…
berry-13 Sep 4, 2026
e23e13e
🌳 feat: List Attached Workspace Trees (#15527)
danny-avila Sep 4, 2026
e795f0c
🏕️ feat: Provision Native Code Workers (#15587)
danny-avila Sep 4, 2026
481c64b
🧃 fix: Decode Blob-Backed MCP Resources (#15601)
danny-avila Sep 4, 2026
3255288
🎖️ fix: Preserve Endpoint Approval Policy Precedence (#15604)
danny-avila Sep 4, 2026
2656f44
style(insights): use Click UI muted token for KPI labels and 32/12 pa…
danielclickh Sep 4, 2026
fddf7e3
🛻 feat: Route Bash Through Attached Workspaces (#15546)
danny-avila Sep 4, 2026
a21c794
🏷️ fix: Record the Media Type of Saved Images, Not the Declared One (…
danny-avila Sep 4, 2026
770238f
🔣 refactor: Replace Mongo Filters With Typed Criteria (#15580)
danny-avila Sep 4, 2026
64d807b
🏛️ refactor: Extract Engine-Neutral Tenant Policy (#15575)
danny-avila Sep 4, 2026
7d9db14
📓 feat: Author Files in Attached Workspaces (#15548)
danny-avila Sep 4, 2026
d21bffa
fix(insights): stop the KPI grid orphaning a card on its own row (#15…
danielclickh Sep 4, 2026
d07527f
style(insights): give panels their own surface in dark mode (#15552)
danielclickh Sep 4, 2026
09da878
🚰 fix: Throttle Shared Link Reads and Aggregate Audit Findings (#15605)
danny-avila Sep 4, 2026
c13990a
🍃 test: Restore Sweep Coverage of Typed-Criteria Methods (#15609)
danny-avila Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
37 changes: 33 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -326,19 +326,28 @@ NODE_MAX_OLD_SPACE_SIZE=6144
# LANGFUSE_FANOUT_BATCH_SEND_SIZE=128
# LANGFUSE_FANOUT_METADATA_CARDINALITY_LIMIT=1000

#=======================#
# OpenTelemetry Tracing #
#=======================#
#===============#
# OpenTelemetry #
#===============#

# Enables backend OpenTelemetry tracing. General backend visibility only;
# use Langfuse for GenAI-specific prompt/model observability.
# OTEL_TRACING_ENABLED=false
# Exports application logs as OpenTelemetry log records, correlated with the
# active trace. Logs below OTEL_LOGS_LEVEL are not exported.
# OTEL_LOGS_ENABLED=false
# OTEL_LOGS_LEVEL=info
# OTEL_SERVICE_NAME=librechat
# OTEL_SERVICE_VERSION=
# Exporter protocol for every signal: http/protobuf (default, port 4318) or grpc (port 4317).
# Per-signal overrides: OTEL_EXPORTER_OTLP_TRACES_PROTOCOL, OTEL_EXPORTER_OTLP_LOGS_PROTOCOL.
# OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
# OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=
# OTEL_EXPORTER_OTLP_HEADERS=
# OTEL_TRACES_EXPORTER=otlp
# OTEL_LOGS_EXPORTER=otlp
# OTEL_TRACES_SAMPLER=parentbased_always_on
# OTEL_LOG_LEVEL=INFO
# OTEL_SDK_DISABLED=false
Expand Down Expand Up @@ -578,7 +587,7 @@ GOOGLE_KEY=user_provided
#============#

OPENAI_API_KEY=user_provided
# OPENAI_MODELS=gpt-5.6,gpt-5.6-terra,gpt-5.6-luna,gpt-5.5,gpt-5.5-pro,chat-latest,gpt-5.4,gpt-5.4-pro,gpt-5.4-mini,gpt-5.4-nano,gpt-5.3-codex,gpt-5.2,gpt-5,gpt-5-codex,gpt-5-mini,gpt-5-nano,o3-pro,o3,o4-mini,gpt-4.1,gpt-4.1-mini,gpt-4.1-nano,o3-mini,o1-pro,o1,gpt-4o,gpt-4o-mini
# OPENAI_MODELS=gpt-6-astra,gpt-5.6,gpt-5.6-terra,gpt-5.6-luna,gpt-5.5,gpt-5.5-pro,chat-latest,gpt-5.4,gpt-5.4-pro,gpt-5.4-mini,gpt-5.4-nano,gpt-5.3-codex,gpt-5.2,gpt-5,gpt-5-codex,gpt-5-mini,gpt-5-nano,o3-pro,o3,o4-mini,gpt-4.1,gpt-4.1-mini,gpt-4.1-nano,o3-mini,o1-pro,o1,gpt-4o,gpt-4o-mini

DEBUG_OPENAI=false

Expand Down Expand Up @@ -805,7 +814,15 @@ TTS_VIOLATION_SCORE=0
STT_VIOLATION_SCORE=0
FORK_VIOLATION_SCORE=0
IMPORT_VIOLATION_SCORE=0
SHARE_VIOLATION_SCORE=0
FILE_UPLOAD_VIOLATION_SCORE=0
# Shared link retrieval re-inspects the whole shared snapshot on every request
# and is reachable without authentication (defaults: 100 per IP and 60 per user,
# both per minute).
# SHARE_IP_MAX=100
# SHARE_IP_WINDOW=1
# SHARE_USER_MAX=60
# SHARE_USER_WINDOW=1
# Per-user limiter for metadata-only /files/usage requests that renew the TTL
# of attachments waiting in queued Agent messages (default: 120 per 15 minutes).
# FILE_USAGE_USER_MAX=120
Expand Down Expand Up @@ -1258,6 +1275,18 @@ HELP_AND_FAQ_URL=https://librechat.ai
# When unset or 0, no pinging is performed (recommended for most use cases)
# REDIS_PING_INTERVAL=300

# Milliseconds a heartbeat PING may go unanswered before the socket is presumed dead and
# reconnected (default: 5000). Applies to REDIS_PING_INTERVAL and the subscriber heartbeat.
# REDIS_PING_TIMEOUT=5000

# Heartbeat interval in seconds for dedicated pub/sub subscriber connections (default: 15, 0 = disabled)
# Subscribers carry no traffic between generations, so a peer that vanished without closing the
# socket would otherwise go unnoticed until the kernel gives up (about 15 minutes at Linux defaults)
# REDIS_SUBSCRIBER_PING_INTERVAL=15

# TCP keepalive idle delay in milliseconds for ioredis sockets (default: 10000, 0 = kernel default)
# REDIS_KEEP_ALIVE=10000

# Force specific cache namespaces to use in-memory storage even when Redis is enabled
# Comma-separated list of CacheKeys
# Defaults to CONFIG_STORE,APP_CONFIG so YAML-derived config stays per-container (safe for blue/green deployments)
Expand Down
1 change: 1 addition & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Domain language

- **Attached code environment**: A principal- or deployment-authorized stateful workspace owned by an outbound `librechat-code` worker on a user-chosen machine or VM. LibreChat selects it and enforces approval policy, Code API authenticates and dispatches to it, and the worker's local sandbox and capability flags remain the final execution ceiling. The environment interface is runtime-neutral: native SRT, WSL2, Docker/NsJail, and future adapters expose the same workspace operations without leaking host paths or runtime configuration into agent tools.
- **Agent run envelope**: the versioned, JSON-safe request contract created after ingress authentication and protocol validation but before agent, provider, tool, or MCP initialization. It carries only the validated protocol payload and the minimum trusted principal identifiers. The execution host rehydrates all runtime state from those identifiers.
- **Agent execution context**: runtime-only, transport-free state rehydrated beside an Agent run envelope. It contains the authenticated user, application configuration, normalized request metadata, and resolved conversation facts needed by initialization, but never Express request/response objects or serialized credentials.
- **Agent execution host**: the protocol-neutral module that owns run admission, disconnect cancellation, provider-start fencing, and terminal settlement. Protocol implementations execute behind its callback interface; HTTP adapters retain validation and final stream rendering.
Expand Down
1 change: 1 addition & 0 deletions api/cache/getLogStores.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const namespaces = {
[ViolationTypes.TTS_LIMIT]: violationCache(ViolationTypes.TTS_LIMIT),
[ViolationTypes.STT_LIMIT]: violationCache(ViolationTypes.STT_LIMIT),
[ViolationTypes.CONVO_ACCESS]: violationCache(ViolationTypes.CONVO_ACCESS),
[ViolationTypes.SHARE_LIMIT]: violationCache(ViolationTypes.SHARE_LIMIT),
[ViolationTypes.TOOL_CALL_LIMIT]: violationCache(ViolationTypes.TOOL_CALL_LIMIT),
[ViolationTypes.FILE_UPLOAD_LIMIT]: violationCache(ViolationTypes.FILE_UPLOAD_LIMIT),
[ViolationTypes.VERIFY_EMAIL_LIMIT]: violationCache(ViolationTypes.VERIFY_EMAIL_LIMIT),
Expand Down
7 changes: 7 additions & 0 deletions api/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ const esModules = [
'@langchain/langgraph-sdk',
'@mistralai/mistralai',
'uuid',
'sanitize-html',
'htmlparser2',
'domhandler',
'domelementtype',
'domutils',
'dom-serializer',
'entities',
].join('|');

module.exports = {
Expand Down
5 changes: 4 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@azure/storage-blob": "^12.30.0",
"@google/genai": "^2.8.0",
"@keyv/redis": "5.1.6",
"@librechat/agents": "^3.7.17",
"@librechat/agents": "^3.7.21",
"@librechat/api": "*",
"@librechat/data-schemas": "*",
"@microsoft/microsoft-graph-client": "^3.0.7",
Expand All @@ -62,6 +62,7 @@
"@opentelemetry/resources": "^2.6.1",
"@opentelemetry/sdk-node": "^0.221.0",
"@opentelemetry/semantic-conventions": "^1.39.0",
"@opentelemetry/winston-transport": "^0.28.0",
"@redis/client": "5.10.0",
"@smithy/node-http-handler": "^4.4.5",
"ai-tokenizer": "^1.0.6",
Expand All @@ -73,6 +74,7 @@
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dedent": "^1.5.3",
"dompurify": "^3.4.12",
"dotenv": "^16.0.3",
"eventsource": "^3.0.2",
"express": "^5.2.1",
Expand All @@ -88,6 +90,7 @@
"https-proxy-agent": "^7.0.6",
"ioredis": "^5.3.2",
"js-yaml": "^4.2.0",
"jsdom": "^26.1.0",
"jsonwebtoken": "^9.0.0",
"jszip": "^3.10.1",
"jwks-rsa": "^3.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,12 @@ describe('callTool generated-content protection', () => {
expect(mockProcessCodeOutput).toHaveBeenCalledWith(
expect.objectContaining({ downloadFallback: true, preparedBuffer: undefined }),
);
/* The cause rides the warning so the failure is diagnosable at all, but
* only through `getSafeErrorMetadata` — the upstream message here is
* `PRIVATE-DOWNLOAD-ERROR`, and that is precisely what must not appear. */
expect(mockLogger.warn).toHaveBeenCalledWith(
'[preflightCodeOutputBatch] Generated artifact 1 could not be inspected',
{ type: 'Error' },
);
expect(JSON.stringify(mockLogger.warn.mock.calls)).not.toContain('PRIVATE-');
expect(res.status).toHaveBeenCalledWith(200);
Expand Down
2 changes: 1 addition & 1 deletion api/server/controllers/agents/__tests__/resume.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1530,7 +1530,7 @@ describe('ResumeAgentController (POST /agents/chat/resume)', () => {
const res = await post(approveBody());

expect(res.status).toBe(400);
expect(mockGetActions).toHaveBeenCalledWith({ agent_id: { $in: [AGENT_ID] } }, false);
expect(mockGetActions).toHaveBeenCalledWith({ agentId: [AGENT_ID] }, false);
expect(mockDecryptMetadata).not.toHaveBeenCalled();
expect(mockGenerationJobManager.approvals.resolve).not.toHaveBeenCalled();
expect(mockInitializeClient).not.toHaveBeenCalled();
Expand Down
2 changes: 1 addition & 1 deletion api/server/controllers/agents/__tests__/v1.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('duplicateAgent', () => {
await duplicateAgent(req, res);

expect(getAgent).toHaveBeenCalledWith({ id: 'agent_123' });
expect(getActions).toHaveBeenCalledWith({ agent_id: 'agent_123' }, true);
expect(getActions).toHaveBeenCalledWith({ agentId: 'agent_123' }, true);
expect(createAgent).toHaveBeenCalledWith(
expect.objectContaining({
id: 'agent_new_123',
Expand Down
8 changes: 4 additions & 4 deletions api/server/controllers/agents/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -1465,7 +1465,7 @@ const duplicateAgentHandler = async (req, res) => {
return res.status(subagentReferenceError.status).json(subagentReferenceError.body);
}

const originalActions = (await db.getActions({ agent_id: id }, true)) ?? [];
const originalActions = (await db.getActions({ agentId: id }, true)) ?? [];
const sanitizedActions = originalActions.map((action) => {
const metadata = { ...(action.metadata || {}) };
for (const field of sensitiveFields) {
Expand Down Expand Up @@ -1550,7 +1550,7 @@ const duplicateAgentHandler = async (req, res) => {
const fullActionId = `${domain}${actionDelimiter}${newActionId}`;

const newAction = await db.updateAction(
{ action_id: newActionId, agent_id: newAgentId },
{ actionId: newActionId, agentId: newAgentId },
{
metadata: action.metadata,
agent_id: newAgentId,
Expand All @@ -1575,7 +1575,7 @@ const duplicateAgentHandler = async (req, res) => {
try {
newAgent = await db.createAgent(newAgentData);
} catch (error) {
await db.deleteActions({ agent_id: newAgentId, user: userId }).catch((cleanupError) => {
await db.deleteActions({ agentId: newAgentId, user: userId }).catch((cleanupError) => {
logger.error(
'[/agents/:id/duplicate] Failed to clean up cloned Actions after Agent creation failed:',
cleanupError,
Expand Down Expand Up @@ -2065,7 +2065,7 @@ const revertAgentVersionHandler = async (req, res) => {
.filter(Boolean);
const actions =
actionIds.length > 0
? ((await db.getActions({ agent_id: id, action_id: { $in: actionIds } }, true)) ?? [])
? ((await db.getActions({ agentId: id, actionId: actionIds }, true)) ?? [])
: [];

if (
Expand Down
Loading
Loading