@librechat/agents 3.2.58 → 3.2.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/cjs/main.cjs +7 -0
  2. package/dist/cjs/stream.cjs +2 -1
  3. package/dist/cjs/stream.cjs.map +1 -1
  4. package/dist/cjs/tools/BashExecutor.cjs +58 -9
  5. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  6. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +4 -2
  7. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  8. package/dist/cjs/tools/CodeExecutor.cjs +57 -7
  9. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  10. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +9 -3
  11. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  12. package/dist/cjs/tools/ToolNode.cjs +19 -1
  13. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  14. package/dist/cjs/tools/eagerEventExecution.cjs +18 -1
  15. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
  16. package/dist/esm/main.mjs +3 -3
  17. package/dist/esm/stream.mjs +2 -1
  18. package/dist/esm/stream.mjs.map +1 -1
  19. package/dist/esm/tools/BashExecutor.mjs +56 -10
  20. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  21. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +4 -2
  22. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  23. package/dist/esm/tools/CodeExecutor.mjs +54 -8
  24. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  25. package/dist/esm/tools/ProgrammaticToolCalling.mjs +9 -3
  26. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  27. package/dist/esm/tools/ToolNode.mjs +20 -2
  28. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  29. package/dist/esm/tools/eagerEventExecution.mjs +18 -2
  30. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
  31. package/dist/types/tools/BashExecutor.d.ts +13 -0
  32. package/dist/types/tools/CodeExecutor.d.ts +14 -0
  33. package/dist/types/tools/ToolNode.d.ts +3 -0
  34. package/dist/types/tools/eagerEventExecution.d.ts +8 -0
  35. package/dist/types/types/tools.d.ts +58 -0
  36. package/package.json +1 -1
  37. package/src/stream.ts +17 -1
  38. package/src/tools/BashExecutor.ts +107 -14
  39. package/src/tools/BashProgrammaticToolCalling.ts +20 -1
  40. package/src/tools/CodeExecutor.ts +113 -9
  41. package/src/tools/ProgrammaticToolCalling.ts +27 -1
  42. package/src/tools/ToolNode.ts +36 -4
  43. package/src/tools/__tests__/BashExecutor.test.ts +39 -0
  44. package/src/tools/__tests__/CodeExecutor.stateful.test.ts +113 -0
  45. package/src/tools/__tests__/ToolNode.session.test.ts +86 -0
  46. package/src/tools/__tests__/eagerEventExecution.session.test.ts +92 -0
  47. package/src/tools/eagerEventExecution.ts +32 -5
  48. package/src/types/tools.ts +65 -0
@@ -52,8 +52,30 @@ export type ToolExecutionPlanCall = {
52
52
  args: unknown;
53
53
  stepId?: string;
54
54
  codeSessionContext?: t.ToolCallRequest['codeSessionContext'];
55
+ runtimeSessionHint?: string;
55
56
  };
56
57
 
58
+ /**
59
+ * Stateful runtime session hint for the remote sandbox: only when
60
+ * `toolExecution.sandbox.statefulSessions` is on; explicit host hint else the
61
+ * conversation `thread_id`. Undefined disables the wire field. Shared by the
62
+ * direct ToolNode path and both event-driven planners so they stay in lockstep.
63
+ */
64
+ export function resolveRuntimeSessionHint(
65
+ toolExecution: t.ToolExecutionConfig | undefined,
66
+ threadId: string | undefined
67
+ ): string | undefined {
68
+ const sandbox = toolExecution?.sandbox;
69
+ if (sandbox?.statefulSessions !== true) {
70
+ return undefined;
71
+ }
72
+ const explicit = sandbox.runtimeSessionHint;
73
+ if (explicit != null && explicit !== '') {
74
+ return explicit;
75
+ }
76
+ return threadId != null && threadId !== '' ? threadId : undefined;
77
+ }
78
+
57
79
  export type ToolExecutionRequestPlan = {
58
80
  allRequests: t.ToolCallRequest[];
59
81
  requests: t.ToolCallRequest[];
@@ -73,15 +95,12 @@ export function buildToolExecutionRequestPlan(args: {
73
95
  args: Record<string, unknown>;
74
96
  stepId?: string;
75
97
  codeSessionContext?: t.ToolCallRequest['codeSessionContext'];
98
+ runtimeSessionHint?: string;
76
99
  rejectedErrorMessage?: string;
77
100
  }> = [];
78
101
 
79
102
  for (const toolCall of args.toolCalls) {
80
- if (
81
- toolCall.id == null ||
82
- toolCall.id === '' ||
83
- toolCall.name === ''
84
- ) {
103
+ if (toolCall.id == null || toolCall.id === '' || toolCall.name === '') {
85
104
  return undefined;
86
105
  }
87
106
  const coercedArgs = coerceRecordArgs(toolCall.args);
@@ -95,6 +114,7 @@ export function buildToolExecutionRequestPlan(args: {
95
114
  args: {},
96
115
  stepId: toolCall.stepId,
97
116
  codeSessionContext: toolCall.codeSessionContext,
117
+ runtimeSessionHint: toolCall.runtimeSessionHint,
98
118
  rejectedErrorMessage:
99
119
  'Invalid tool call arguments: expected a JSON object.',
100
120
  });
@@ -106,6 +126,7 @@ export function buildToolExecutionRequestPlan(args: {
106
126
  args: coercedArgs,
107
127
  stepId: toolCall.stepId,
108
128
  codeSessionContext: toolCall.codeSessionContext,
129
+ runtimeSessionHint: toolCall.runtimeSessionHint,
109
130
  });
110
131
  }
111
132
 
@@ -123,6 +144,12 @@ export function buildToolExecutionRequestPlan(args: {
123
144
  if (toolCall.codeSessionContext != null) {
124
145
  request.codeSessionContext = toolCall.codeSessionContext;
125
146
  }
147
+ if (
148
+ toolCall.runtimeSessionHint != null &&
149
+ toolCall.runtimeSessionHint !== ''
150
+ ) {
151
+ request.runtimeSessionHint = toolCall.runtimeSessionHint;
152
+ }
126
153
  return request;
127
154
  });
128
155
  const requests = allRequests.filter(
@@ -292,6 +292,15 @@ export type CodeExecutionToolParams =
292
292
  files?: CodeEnvFile[];
293
293
  /** Optional host-supplied Code API auth headers. */
294
294
  authHeaders?: CodeApiAuthHeaders;
295
+ /**
296
+ * Advertise best-effort stateful sessions in the tool description
297
+ * (variables/files may persist between calls, may reset). Prompt text
298
+ * only, and it must be set here because the description is bound to the
299
+ * LLM at construction time. Pair it with the run-scoped
300
+ * `toolExecution.sandbox.statefulSessions` gate, which drives the wire
301
+ * hint — set both from one flag so the prompt and the backend agree.
302
+ */
303
+ statefulSessions?: boolean;
295
304
  };
296
305
 
297
306
  export type CodeApiAuthHeaderMap = Record<string, string>;
@@ -347,6 +356,13 @@ export type ExecuteResult = {
347
356
  stdout: string;
348
357
  stderr: string;
349
358
  files?: FileRefs;
359
+ /**
360
+ * Durable runtime session id echoed by a stateful Code API backend
361
+ * (hash of tenant+user+hint). Additive; absent on stateless servers.
362
+ */
363
+ runtime_session_id?: string;
364
+ /** Whether this execution reused a warm runtime session or started fresh. */
365
+ runtime_status?: 'new' | 'reused';
350
366
  };
351
367
 
352
368
  /** JSON Schema type definition for tool parameters */
@@ -413,6 +429,12 @@ export type ToolCallRequest = {
413
429
  session_id: string;
414
430
  files?: CodeEnvFile[];
415
431
  };
432
+ /**
433
+ * Stable runtime session hint for stateful sandbox sessions. Orthogonal to
434
+ * `codeSessionContext` (which threads the transient exec-session for file
435
+ * continuity): the hint identifies the durable server-side runtime session.
436
+ */
437
+ runtimeSessionHint?: string;
416
438
  };
417
439
 
418
440
  /** Batch request containing ALL tool calls for a graph step */
@@ -969,6 +991,32 @@ export type CloudflareSandboxExecutionConfig = {
969
991
  postEditSyntaxCheck?: LocalExecutionConfig['postEditSyntaxCheck'];
970
992
  };
971
993
 
994
+ export type SandboxExecutionConfig = {
995
+ /**
996
+ * Opt into best-effort stateful runtime sessions on the remote Code API
997
+ * (its warm per-session MicroVM backend). This gate is run-scoped: it only
998
+ * controls the wire behavior (ToolNode injecting the session hint on
999
+ * execute_code/bash calls). The transport is otherwise unchanged.
1000
+ *
1001
+ * It does NOT change the model-facing tool description. Tool descriptions are
1002
+ * bound to the LLM at construction time (`createCodeExecutionTool` /
1003
+ * `createBashExecutionTool`), before this run config is applied inside the
1004
+ * graph, so they can only be adjusted via the tools' own `statefulSessions`
1005
+ * factory param. Set BOTH from one flag (as LibreChat does): with this on but
1006
+ * the factory param off, the backend runs statefully while the model is still
1007
+ * told the environment is stateless (non-corrupting — the model just won't
1008
+ * exploit persistence).
1009
+ */
1010
+ statefulSessions?: boolean;
1011
+ /**
1012
+ * Stable identity for the runtime session (e.g. the conversation id). The
1013
+ * server derives the real session id as hash(tenant, user, hint), so this
1014
+ * is never a security boundary. Falls back to `configurable.thread_id` when
1015
+ * omitted.
1016
+ */
1017
+ runtimeSessionHint?: string;
1018
+ };
1019
+
972
1020
  export type ToolExecutionConfig = {
973
1021
  /** `sandbox` preserves the remote Code API behavior and is the default. */
974
1022
  engine?: ToolExecutionEngine;
@@ -976,6 +1024,8 @@ export type ToolExecutionConfig = {
976
1024
  local?: LocalExecutionConfig;
977
1025
  /** Cloudflare Sandbox execution settings used when `engine` is `cloudflare-sandbox`. */
978
1026
  cloudflare?: CloudflareSandboxExecutionConfig;
1027
+ /** Remote sandbox settings; applies when `engine` is `sandbox` or omitted. */
1028
+ sandbox?: SandboxExecutionConfig;
979
1029
  };
980
1030
 
981
1031
  export type ProgrammaticCache = {
@@ -1099,6 +1149,10 @@ export type ProgrammaticExecutionResponse = {
1099
1149
  stderr?: string;
1100
1150
  files?: FileRefs;
1101
1151
 
1152
+ /** Durable runtime session echo from a stateful backend (additive). */
1153
+ runtime_session_id?: string;
1154
+ runtime_status?: 'new' | 'reused';
1155
+
1102
1156
  /** Present when status='error' */
1103
1157
  error?: string;
1104
1158
  };
@@ -1110,6 +1164,9 @@ export type ProgrammaticExecutionArtifact = {
1110
1164
  /** Execution session — see `CodeSessionContext.session_id`. */
1111
1165
  session_id?: string;
1112
1166
  files?: FileRefs;
1167
+ /** Durable runtime session echo from a stateful backend (additive). */
1168
+ runtime_session_id?: string;
1169
+ runtime_status?: 'new' | 'reused';
1113
1170
  };
1114
1171
 
1115
1172
  /** Parameters for creating a bash execution tool (same API as CodeExecutor, bash-only) */
@@ -1134,6 +1191,11 @@ export type ProgrammaticToolCallingParams = {
1134
1191
  debug?: boolean;
1135
1192
  /** Optional host-supplied Code API auth headers. */
1136
1193
  authHeaders?: CodeApiAuthHeaders;
1194
+ /* No `statefulSessions` here: PTC is stateless in v1. The initial
1195
+ * /exec/programmatic request still forwards a ToolNode-injected
1196
+ * `_runtime_session_hint` when present, but there is no factory-level opt-in
1197
+ * to advertise (it would be a no-op). Re-add with real behavior when PTC
1198
+ * stateful prompting lands. */
1137
1199
  };
1138
1200
 
1139
1201
  // ============================================================================
@@ -1166,6 +1228,9 @@ export type CodeExecutionArtifact = {
1166
1228
  /** Execution session — see `CodeSessionContext.session_id`. */
1167
1229
  session_id?: string;
1168
1230
  files?: FileRefs;
1231
+ /** Durable runtime session echo from a stateful backend (additive). */
1232
+ runtime_session_id?: string;
1233
+ runtime_status?: 'new' | 'reused';
1169
1234
  };
1170
1235
 
1171
1236
  /**