From 2c2903ff7e6232dbca5026395a9f31454c40428e Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 30 Aug 2026 01:38:23 -0400 Subject: [PATCH 01/11] feat: add attached stateful code environments --- api/app/clients/tools/util/handleTools.js | 3 + api/server/services/ToolService.js | 6 ++ client/src/common/agents-types.ts | 2 + .../Agents/Advanced/StatefulSessions.tsx | 38 +++++++++++ .../SidePanel/Agents/AgentPanel.tsx | 2 + .../SidePanel/Agents/AgentSelect.tsx | 1 + client/src/locales/en/translation.json | 3 + e2e/config/librechat.e2e.yaml | 1 + e2e/playwright.config.mock.ts | 17 +++++ e2e/setup/fake-model.js | 43 ++++++++++++ e2e/specs/mock/stateful-code-bridge.spec.ts | 66 +++++++++++++++++++ librechat.example.yaml | 12 ++++ packages/api/src/agents/execution.spec.ts | 64 ++++++++++++++++++ packages/api/src/agents/execution.ts | 48 ++++++++++++-- packages/api/src/agents/initialize.ts | 3 + packages/api/src/agents/lazySubagents.ts | 2 + packages/api/src/agents/prewarm.spec.ts | 24 +++++++ packages/api/src/agents/prewarm.ts | 21 +++--- packages/api/src/agents/validation.ts | 4 ++ .../specs/config-schemas.spec.ts | 44 +++++++++++++ packages/data-provider/src/config.ts | 36 ++++++++++ packages/data-provider/src/schemas.ts | 1 + packages/data-provider/src/types.ts | 7 ++ .../data-provider/src/types/assistants.ts | 4 ++ packages/data-schemas/src/schema/agent.ts | 3 + packages/data-schemas/src/types/agent.ts | 1 + 26 files changed, 441 insertions(+), 15 deletions(-) create mode 100644 e2e/specs/mock/stateful-code-bridge.spec.ts diff --git a/api/app/clients/tools/util/handleTools.js b/api/app/clients/tools/util/handleTools.js index ec75adea763..0ec1cc02ca3 100644 --- a/api/app/clients/tools/util/handleTools.js +++ b/api/app/clients/tools/util/handleTools.js @@ -356,6 +356,9 @@ const loadTools = async ({ resolveCodeExecutionContext({ statefulSessions, environment: agent?.stateful_code_environment, + environmentId: agent?.code_environment_id, + environments: + options.req?.config?.endpoints?.agents?.statefulCodeSessions?.environments, userId: user, agentId: agent?.id, conversationId: options.req?.body?.conversationId, diff --git a/api/server/services/ToolService.js b/api/server/services/ToolService.js index 200f81fbd03..f133df9ed9c 100644 --- a/api/server/services/ToolService.js +++ b/api/server/services/ToolService.js @@ -785,6 +785,8 @@ async function loadToolDefinitionsWrapper({ enabledCapabilities.has(AgentCapabilities.stateful_code_sessions) && agent.stateful_code_sessions === true, environment: agent.stateful_code_environment, + environmentId: agent.code_environment_id, + environments: req.config?.endpoints?.agents?.statefulCodeSessions?.environments, userId: req.user.id, agentId: agent.id, conversationId: runtimeRequestBody?.conversationId, @@ -1642,6 +1644,8 @@ async function loadAgentTools({ resolveCodeExecutionContext({ statefulSessions: statefulCodeSessions, environment: agent.stateful_code_environment, + environmentId: agent.code_environment_id, + environments: req.config?.endpoints?.agents?.statefulCodeSessions?.environments, userId: req.user.id, agentId: agent.id, conversationId: requestBody?.conversationId ?? req.body?.conversationId, @@ -2022,6 +2026,8 @@ async function loadToolsForExecution({ const codeExecutionContext = resolveCodeExecutionContext({ statefulSessions: statefulCodeSessions, environment: agent?.stateful_code_environment, + environmentId: agent?.code_environment_id, + environments: req.config?.endpoints?.agents?.statefulCodeSessions?.environments, userId: req.user.id, agentId: agent?.id, conversationId: conversationId ?? runtimeRequestBody?.conversationId, diff --git a/client/src/common/agents-types.ts b/client/src/common/agents-types.ts index c5ac569ac21..9800361d122 100644 --- a/client/src/common/agents-types.ts +++ b/client/src/common/agents-types.ts @@ -47,6 +47,8 @@ export type AgentForm = { memory_scope?: MemoryScope; /** Sharing scope for stateful Code API workspaces. */ stateful_code_environment?: StatefulCodeEnvironment; + /** Operator-configured managed or attached execution environment. */ + code_environment_id?: string; provider?: AgentProvider | OptionWithIcon; /** @deprecated Use edges instead */ agent_ids?: string[]; diff --git a/client/src/components/SidePanel/Agents/Advanced/StatefulSessions.tsx b/client/src/components/SidePanel/Agents/Advanced/StatefulSessions.tsx index 77d6445e592..425ae5fa103 100644 --- a/client/src/components/SidePanel/Agents/Advanced/StatefulSessions.tsx +++ b/client/src/components/SidePanel/Agents/Advanced/StatefulSessions.tsx @@ -39,7 +39,9 @@ export default function StatefulSessions() { const enabled = watch(AgentCapabilities.stateful_code_sessions) ?? false; const codeEnabled = watch(AgentCapabilities.execute_code); const environment = watch('stateful_code_environment') ?? 'user'; + const codeEnvironmentId = watch('code_environment_id'); const configuredEnvironments = agentsConfig?.statefulCodeSessions?.allowedEnvironments; + const executionEnvironments = agentsConfig?.statefulCodeSessions?.environments ?? []; const allowedEnvironments = resolveAllowedStatefulCodeEnvironments(configuredEnvironments); const handleChange = (value: boolean) => { @@ -91,6 +93,42 @@ export default function StatefulSessions() { {enabled && codeEnabled === true && (
+ {executionEnvironments.length > 0 && ( + <> + + +

+ {localize('com_nav_info_code_environment')} +

+ + )}