@librechat/agents 3.1.78 → 3.1.80-dev.0

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 (76) hide show
  1. package/dist/cjs/llm/anthropic/index.cjs +44 -55
  2. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  3. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +33 -21
  4. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +0 -4
  6. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  7. package/dist/cjs/messages/anthropicToolCache.cjs +48 -15
  8. package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -1
  9. package/dist/cjs/messages/format.cjs +97 -14
  10. package/dist/cjs/messages/format.cjs.map +1 -1
  11. package/dist/cjs/tools/BashExecutor.cjs +10 -2
  12. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  13. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +2 -1
  14. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  15. package/dist/cjs/tools/CodeExecutor.cjs +16 -5
  16. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  17. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +9 -4
  18. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  19. package/dist/cjs/tools/ToolNode.cjs +63 -40
  20. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  21. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +14 -16
  22. package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
  23. package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
  24. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  25. package/dist/esm/llm/anthropic/index.mjs +43 -54
  26. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  27. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +33 -21
  28. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  29. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +0 -4
  30. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  31. package/dist/esm/messages/anthropicToolCache.mjs +48 -15
  32. package/dist/esm/messages/anthropicToolCache.mjs.map +1 -1
  33. package/dist/esm/messages/format.mjs +97 -14
  34. package/dist/esm/messages/format.mjs.map +1 -1
  35. package/dist/esm/tools/BashExecutor.mjs +10 -2
  36. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  37. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +2 -1
  38. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  39. package/dist/esm/tools/CodeExecutor.mjs +16 -5
  40. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  41. package/dist/esm/tools/ProgrammaticToolCalling.mjs +9 -4
  42. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  43. package/dist/esm/tools/ToolNode.mjs +63 -40
  44. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  45. package/dist/esm/tools/local/LocalExecutionEngine.mjs +14 -16
  46. package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
  47. package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
  48. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  49. package/dist/types/llm/anthropic/index.d.ts +1 -9
  50. package/dist/types/messages/anthropicToolCache.d.ts +5 -5
  51. package/dist/types/types/tools.d.ts +82 -17
  52. package/package.json +1 -1
  53. package/src/llm/anthropic/index.ts +55 -64
  54. package/src/llm/anthropic/llm.spec.ts +585 -0
  55. package/src/llm/anthropic/utils/message_inputs.ts +36 -21
  56. package/src/llm/anthropic/utils/message_outputs.ts +0 -4
  57. package/src/llm/anthropic/utils/server-tool-inputs.test.ts +95 -13
  58. package/src/messages/__tests__/anthropicToolCache.test.ts +46 -0
  59. package/src/messages/anthropicToolCache.ts +70 -25
  60. package/src/messages/format.ts +117 -18
  61. package/src/messages/formatAgentMessages.test.ts +202 -1
  62. package/src/scripts/code_exec_multi_session.ts +4 -4
  63. package/src/specs/summarization.test.ts +3 -3
  64. package/src/tools/BashExecutor.ts +11 -3
  65. package/src/tools/BashProgrammaticToolCalling.ts +6 -6
  66. package/src/tools/CodeExecutor.ts +17 -6
  67. package/src/tools/ProgrammaticToolCalling.ts +14 -10
  68. package/src/tools/ToolNode.ts +85 -48
  69. package/src/tools/__tests__/LocalExecutionRoots.test.ts +8 -0
  70. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +9 -2
  71. package/src/tools/__tests__/ToolNode.session.test.ts +131 -50
  72. package/src/tools/local/LocalExecutionEngine.ts +55 -54
  73. package/src/tools/local/LocalExecutionTools.ts +2 -2
  74. package/src/tools/local/LocalProgrammaticToolCalling.ts +23 -6
  75. package/src/types/diff.d.ts +15 -0
  76. package/src/types/tools.ts +79 -17
@@ -121,39 +121,69 @@ function normalizeApprovalDecisions(callIds, resumeValue) {
121
121
  * - `artifact.session_id` (the `sessionId` arg here) is the EXEC session
122
122
  * — the sandbox VM that ran the code. It's transient and torn down
123
123
  * post-execution; subsequent calls cannot reuse it as a sandbox.
124
- * - `file.session_id` on each `artifact.files[i]` is the STORAGE
124
+ * - `file.storage_session_id` on each `artifact.files[i]` is the STORAGE
125
125
  * session — the file-server bucket prefix where the artifact actually
126
126
  * lives and is served from.
127
127
  *
128
- * Per-file `session_id` is preserved (not overwritten with the exec id)
129
- * because `_injected_files` are looked up against the file-server's
130
- * storage path on subsequent tool calls. Stomping the storage id with
131
- * the exec id silently 404s every follow-up tool call within the same
132
- * run — `cat /mnt/data/foo.txt` reports "No such file or directory"
133
- * because the worker can't mount a file at a path the storage doesn't
134
- * know about. Fall back to `sessionId` only when the per-file id is
135
- * absent (older worker payloads).
128
+ * Per-file `storage_session_id` is preserved (not overwritten with the
129
+ * exec id) because `_injected_files` are looked up against the
130
+ * file-server's storage path on subsequent tool calls. Stomping the
131
+ * storage id with the exec id silently 404s every follow-up tool call
132
+ * within the same run — `cat /mnt/data/foo.txt` reports "No such file
133
+ * or directory" because the worker can't mount a file at a path the
134
+ * storage doesn't know about. Fall back to the exec id only when the
135
+ * per-file id is absent (e.g. inline `content` files have no persistent
136
+ * storage location).
136
137
  */
137
- function updateCodeSession(sessions, sessionId, files) {
138
+ /**
139
+ * Builds a `CodeEnvFile` ref from an arbitrary `FileRef`-like input,
140
+ * narrowing onto the discriminated union: `kind: 'skill'` requires
141
+ * `version`, other kinds forbid it.
142
+ *
143
+ * Defaults `kind` to `'user'` when unset — most ad-hoc files are
144
+ * user-private; shared resources (skills/agents) populate their kind
145
+ * upstream. A skill ref missing `version` falls back to `'user'` so
146
+ * the upstream contract bug surfaces as a degraded sessionKey rather
147
+ * than a runtime crash; primeSkillFiles is the only writer, and it
148
+ * always sets `version` — see LC packages/api/src/agents/skillFiles.ts.
149
+ */
150
+ function toInjectedFileRef(file, execSessionId) {
151
+ const base = {
152
+ id: file.id,
153
+ name: file.name,
154
+ /* Inline `content` files have no persistent storage location;
155
+ * fall back to the execution session id for those entries. */
156
+ storage_session_id: file.storage_session_id ?? execSessionId,
157
+ };
158
+ const kind = file.kind ?? 'user';
159
+ if (kind === 'skill' && file.version != null) {
160
+ return { ...base, kind: 'skill', version: file.version };
161
+ }
162
+ if (kind === 'agent') {
163
+ return { ...base, kind: 'agent' };
164
+ }
165
+ return { ...base, kind: 'user' };
166
+ }
167
+ function updateCodeSession(sessions, execSessionId, files) {
138
168
  const newFiles = files ?? [];
139
169
  const existingSession = sessions.get(Constants.EXECUTE_CODE);
140
170
  const existingFiles = existingSession?.files ?? [];
141
171
  if (newFiles.length > 0) {
142
172
  const filesWithSession = newFiles.map((file) => ({
143
173
  ...file,
144
- session_id: file.session_id ?? sessionId,
174
+ storage_session_id: file.storage_session_id ?? execSessionId,
145
175
  }));
146
176
  const newFileNames = new Set(filesWithSession.map((f) => f.name));
147
177
  const filteredExisting = existingFiles.filter((f) => !newFileNames.has(f.name));
148
178
  sessions.set(Constants.EXECUTE_CODE, {
149
- session_id: sessionId,
179
+ session_id: execSessionId,
150
180
  files: [...filteredExisting, ...filesWithSession],
151
181
  lastUpdated: Date.now(),
152
182
  });
153
183
  }
154
184
  else {
155
185
  sessions.set(Constants.EXECUTE_CODE, {
156
- session_id: sessionId,
186
+ session_id: execSessionId,
157
187
  files: existingFiles,
158
188
  lastUpdated: Date.now(),
159
189
  });
@@ -240,7 +270,10 @@ class ToolNode extends RunnableCallable {
240
270
  this.loadRuntimeTools = loadRuntimeTools;
241
271
  this.errorHandler = errorHandler;
242
272
  this.toolUsageCount = new Map();
243
- this.toolRegistry = resolveLocalToolRegistry({ toolRegistry, toolExecution });
273
+ this.toolRegistry = resolveLocalToolRegistry({
274
+ toolRegistry,
275
+ toolExecution,
276
+ });
244
277
  this.sessions = sessions;
245
278
  this.eventDrivenMode = eventDrivenMode ?? false;
246
279
  this.agentId = agentId;
@@ -507,19 +540,14 @@ class ToolNode extends RunnableCallable {
507
540
  */
508
541
  if (CODE_EXECUTION_TOOLS.has(call.name)) {
509
542
  const codeSession = this.sessions?.get(Constants.EXECUTE_CODE);
510
- if (codeSession?.session_id != null && codeSession.session_id !== '') {
543
+ const execSessionId = codeSession?.session_id;
544
+ if (execSessionId != null && execSessionId !== '') {
511
545
  invokeParams = {
512
546
  ...invokeParams,
513
- session_id: codeSession.session_id,
547
+ session_id: execSessionId,
514
548
  };
515
- if (codeSession.files != null && codeSession.files.length > 0) {
516
- const fileRefs = codeSession.files.map((file) => ({
517
- session_id: file.session_id ?? codeSession.session_id,
518
- id: file.id,
519
- name: file.name,
520
- ...(file.entity_id != null ? { entity_id: file.entity_id } : {}),
521
- }));
522
- invokeParams._injected_files = fileRefs;
549
+ if (codeSession?.files != null && codeSession.files.length > 0) {
550
+ invokeParams._injected_files = codeSession.files.map((file) => toInjectedFileRef(file, execSessionId));
523
551
  }
524
552
  }
525
553
  }
@@ -735,8 +763,7 @@ class ToolNode extends RunnableCallable {
735
763
  // survives `run()`'s clear, so a resume sees the original
736
764
  // assignment.)
737
765
  const cachedTurn = call.id != null && call.id !== ''
738
- ? this.directPathTurns.get(call.id) ??
739
- this.toolCallTurns.get(call.id)
766
+ ? (this.directPathTurns.get(call.id) ?? this.toolCallTurns.get(call.id))
740
767
  : undefined;
741
768
  if (cachedTurn != null) {
742
769
  usageCount = cachedTurn;
@@ -872,9 +899,7 @@ class ToolNode extends RunnableCallable {
872
899
  return this.blockDirectCall({
873
900
  call,
874
901
  resolvedArgs,
875
- reason: decision.reason ??
876
- preResult.reason ??
877
- 'Rejected by user',
902
+ reason: decision.reason ?? preResult.reason ?? 'Rejected by user',
878
903
  hookRegistry,
879
904
  runId,
880
905
  threadId,
@@ -1133,16 +1158,12 @@ class ToolNode extends RunnableCallable {
1133
1158
  if (!codeSession) {
1134
1159
  return undefined;
1135
1160
  }
1161
+ const execSessionId = codeSession.session_id;
1136
1162
  const context = {
1137
- session_id: codeSession.session_id,
1163
+ session_id: execSessionId,
1138
1164
  };
1139
1165
  if (codeSession.files && codeSession.files.length > 0) {
1140
- context.files = codeSession.files.map((file) => ({
1141
- session_id: file.session_id ?? codeSession.session_id,
1142
- id: file.id,
1143
- name: file.name,
1144
- ...(file.entity_id != null ? { entity_id: file.entity_id } : {}),
1145
- }));
1166
+ context.files = codeSession.files.map((file) => toInjectedFileRef(file, execSessionId));
1146
1167
  }
1147
1168
  return context;
1148
1169
  }
@@ -1167,10 +1188,11 @@ class ToolNode extends RunnableCallable {
1167
1188
  continue;
1168
1189
  }
1169
1190
  const artifact = result.artifact;
1170
- if (artifact?.session_id == null || artifact.session_id === '') {
1191
+ const execSessionId = artifact?.session_id;
1192
+ if (execSessionId == null || execSessionId === '') {
1171
1193
  continue;
1172
1194
  }
1173
- updateCodeSession(this.sessions, artifact.session_id, artifact.files);
1195
+ updateCodeSession(this.sessions, execSessionId, artifact?.files);
1174
1196
  }
1175
1197
  }
1176
1198
  /**
@@ -1203,8 +1225,9 @@ class ToolNode extends RunnableCallable {
1203
1225
  }
1204
1226
  if (this.sessions && CODE_EXECUTION_TOOLS.has(call.name)) {
1205
1227
  const artifact = toolMessage.artifact;
1206
- if (artifact?.session_id != null && artifact.session_id !== '') {
1207
- updateCodeSession(this.sessions, artifact.session_id, artifact.files);
1228
+ const execSessionId = artifact?.session_id;
1229
+ if (execSessionId != null && execSessionId !== '') {
1230
+ updateCodeSession(this.sessions, execSessionId, artifact?.files);
1208
1231
  }
1209
1232
  }
1210
1233
  // Dispatch ON_RUN_STEP_COMPLETED via custom event (same path as dispatchToolEvents)