@librechat/agents 3.1.88 → 3.1.90

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 (96) hide show
  1. package/dist/cjs/graphs/Graph.cjs +25 -1
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hooks/executeHooks.cjs +14 -7
  4. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/index.cjs +8 -2
  6. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  7. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +34 -0
  8. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  9. package/dist/cjs/main.cjs +9 -0
  10. package/dist/cjs/main.cjs.map +1 -1
  11. package/dist/cjs/stream.cjs +115 -8
  12. package/dist/cjs/stream.cjs.map +1 -1
  13. package/dist/cjs/tools/BashExecutor.cjs +10 -9
  14. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  15. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +12 -8
  16. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  17. package/dist/cjs/tools/CodeExecutor.cjs +35 -11
  18. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  19. package/dist/cjs/tools/CodeSessionFileSummary.cjs +63 -0
  20. package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -0
  21. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +16 -12
  22. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  23. package/dist/cjs/tools/ToolNode.cjs +32 -12
  24. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  25. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +319 -29
  26. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  27. package/dist/cjs/tools/toolOutputReferences.cjs +8 -0
  28. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  29. package/dist/cjs/utils/events.cjs +3 -1
  30. package/dist/cjs/utils/events.cjs.map +1 -1
  31. package/dist/esm/graphs/Graph.mjs +25 -1
  32. package/dist/esm/graphs/Graph.mjs.map +1 -1
  33. package/dist/esm/hooks/executeHooks.mjs +14 -7
  34. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  35. package/dist/esm/llm/anthropic/index.mjs +9 -3
  36. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  37. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +33 -1
  38. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  39. package/dist/esm/main.mjs +2 -1
  40. package/dist/esm/main.mjs.map +1 -1
  41. package/dist/esm/stream.mjs +115 -8
  42. package/dist/esm/stream.mjs.map +1 -1
  43. package/dist/esm/tools/BashExecutor.mjs +11 -10
  44. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  45. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +13 -9
  46. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  47. package/dist/esm/tools/CodeExecutor.mjs +29 -12
  48. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  49. package/dist/esm/tools/CodeSessionFileSummary.mjs +60 -0
  50. package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -0
  51. package/dist/esm/tools/ProgrammaticToolCalling.mjs +17 -13
  52. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  53. package/dist/esm/tools/ToolNode.mjs +32 -12
  54. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  55. package/dist/esm/tools/subagent/SubagentExecutor.mjs +320 -31
  56. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  57. package/dist/esm/tools/toolOutputReferences.mjs +8 -1
  58. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  59. package/dist/esm/utils/events.mjs +3 -1
  60. package/dist/esm/utils/events.mjs.map +1 -1
  61. package/dist/types/graphs/Graph.d.ts +8 -0
  62. package/dist/types/llm/anthropic/index.d.ts +3 -1
  63. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +4 -0
  64. package/dist/types/tools/BashExecutor.d.ts +3 -3
  65. package/dist/types/tools/CodeExecutor.d.ts +10 -3
  66. package/dist/types/tools/CodeSessionFileSummary.d.ts +3 -0
  67. package/dist/types/tools/ProgrammaticToolCalling.d.ts +4 -4
  68. package/dist/types/tools/subagent/SubagentExecutor.d.ts +8 -5
  69. package/dist/types/types/tools.d.ts +11 -3
  70. package/dist/types/utils/events.d.ts +1 -1
  71. package/package.json +1 -1
  72. package/src/__tests__/stream.eagerEventExecution.test.ts +1073 -221
  73. package/src/graphs/Graph.ts +27 -5
  74. package/src/hooks/__tests__/executeHooks.test.ts +38 -0
  75. package/src/hooks/executeHooks.ts +27 -7
  76. package/src/llm/anthropic/index.ts +27 -3
  77. package/src/llm/anthropic/llm.spec.ts +60 -1
  78. package/src/llm/anthropic/utils/message_inputs.ts +46 -0
  79. package/src/specs/subagent.test.ts +87 -1
  80. package/src/stream.ts +163 -12
  81. package/src/tools/BashExecutor.ts +21 -10
  82. package/src/tools/BashProgrammaticToolCalling.ts +21 -9
  83. package/src/tools/CodeExecutor.ts +55 -12
  84. package/src/tools/CodeSessionFileSummary.ts +80 -0
  85. package/src/tools/ProgrammaticToolCalling.ts +25 -12
  86. package/src/tools/ToolNode.ts +142 -116
  87. package/src/tools/__tests__/BashExecutor.test.ts +9 -0
  88. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +43 -0
  89. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +100 -16
  90. package/src/tools/__tests__/SubagentExecutor.test.ts +540 -6
  91. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +278 -14
  92. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +52 -0
  93. package/src/tools/__tests__/subagentHooks.test.ts +237 -0
  94. package/src/tools/subagent/SubagentExecutor.ts +514 -36
  95. package/src/types/tools.ts +11 -3
  96. package/src/utils/events.ts +4 -2
@@ -8,6 +8,7 @@ import type * as t from '@/types';
8
8
  import { Constants } from '@/common';
9
9
  import {
10
10
  createProgrammaticToolCallingTool,
11
+ createProgrammaticToolCallingSchema,
11
12
  formatCompletedResponse,
12
13
  extractUsedToolNames,
13
14
  filterToolsByUsage,
@@ -15,6 +16,7 @@ import {
15
16
  normalizeToPythonIdentifier,
16
17
  unwrapToolResponse,
17
18
  } from '../ProgrammaticToolCalling';
19
+ import { createBashProgrammaticToolCallingSchema } from '../BashProgrammaticToolCalling';
18
20
  import {
19
21
  createProgrammaticToolRegistry,
20
22
  createGetTeamMembersTool,
@@ -24,6 +26,33 @@ import {
24
26
  } from '@/test/mockTools';
25
27
 
26
28
  describe('ProgrammaticToolCalling', () => {
29
+ describe('tool descriptions', () => {
30
+ it('explains Python inner-tool call and result shape', () => {
31
+ const schema = createProgrammaticToolCallingSchema();
32
+ const description = schema.properties.code.description;
33
+
34
+ expect(description).toContain('keyword args only');
35
+ expect(description).toContain('never pass a dict');
36
+ expect(description).toContain('Tool results are decoded Python values');
37
+ });
38
+
39
+ it('explains bash inner-tool stdout shape', () => {
40
+ const schema = createBashProgrammaticToolCallingSchema();
41
+ const description = schema.properties.code.description;
42
+
43
+ expect(description).toContain('jq: use fromjson? // .');
44
+ expect(description).toContain('again on JSON-string fields');
45
+ expect(description).toContain('arrays may contain strings');
46
+ expect(description).toContain('raw=$(tool');
47
+ expect(description).toContain('direct tool > file may be empty');
48
+ expect(description).toContain('/mnt/data/sf.json');
49
+ expect(description).toContain(
50
+ 'failed executions do not register new files'
51
+ );
52
+ expect(description).toContain('not later-call storage');
53
+ });
54
+ });
55
+
27
56
  describe('executeTools', () => {
28
57
  let toolMap: t.ToolMap;
29
58
 
@@ -656,13 +685,26 @@ for member in team:
656
685
  expect(output).toContain('stderr:\nWarning: deprecated function');
657
686
  });
658
687
 
659
- it('preserves files on the artifact but omits them from the LLM-facing output', () => {
660
- /* The post-execution file summary was removed because it
661
- * misled the model more than it helped — especially with
662
- * bash, where models naturally `ls /mnt/data/` to discover
663
- * available files. The artifact still carries every file
664
- * so the host's session-tracking layer stays in sync;
665
- * the LLM just doesn't see the prescriptive listing. */
688
+ it('adds a /tmp scratch reminder when source code used /tmp', () => {
689
+ const response: t.ProgrammaticExecutionResponse = {
690
+ status: 'completed',
691
+ stdout: 'done\n',
692
+ stderr: '',
693
+ files: [],
694
+ session_id: 'sess_abc123',
695
+ };
696
+
697
+ const [output] = formatCompletedResponse(
698
+ response,
699
+ 'tool "{}" > /tmp/result.json'
700
+ );
701
+
702
+ expect(output).toContain('stdout:\ndone');
703
+ expect(output).toContain('/tmp files are same-call scratch only');
704
+ expect(output).toContain('use /mnt/data for files needed later');
705
+ });
706
+
707
+ it('preserves files on the artifact and summarizes them without listing paths', () => {
666
708
  const response: t.ProgrammaticExecutionResponse = {
667
709
  status: 'completed',
668
710
  stdout: 'Generated report\n',
@@ -677,9 +719,12 @@ for member in team:
677
719
 
678
720
  const [output, artifact] = formatCompletedResponse(response);
679
721
 
680
- /* Tool result text is stdout/stderr only. */
681
722
  expect(output).toContain('stdout:\nGenerated report');
682
- expect(output).not.toContain('Generated files:');
723
+ expect(output).toContain('Generated files:');
724
+ expect(output).toContain(
725
+ 'Session files: 2 persisted file(s) are available in /mnt/data, including 0 image(s).'
726
+ );
727
+ expect(output).toContain('do not invent download links');
683
728
  expect(output).not.toContain('Available files');
684
729
  expect(output).not.toContain('report.pdf');
685
730
  expect(output).not.toContain('SKILL.md');
@@ -691,6 +736,25 @@ for member in team:
691
736
  expect(artifact.files).toHaveLength(3);
692
737
  expect(artifact.files).toEqual(response.files);
693
738
  });
739
+
740
+ it('omits the generated-file summary for inherited-only files', () => {
741
+ const response: t.ProgrammaticExecutionResponse = {
742
+ status: 'completed',
743
+ stdout: 'No new files\n',
744
+ stderr: '',
745
+ files: [
746
+ { id: 'i1', name: 'skills/SKILL.md', inherited: true },
747
+ { id: 'i2', name: 'inputs/source.csv', inherited: true },
748
+ ],
749
+ session_id: 'sess_abc123',
750
+ };
751
+
752
+ const [output, artifact] = formatCompletedResponse(response);
753
+
754
+ expect(output).toBe('stdout:\nNo new files');
755
+ expect(output).not.toContain('Generated files:');
756
+ expect(artifact.files).toEqual(response.files);
757
+ });
694
758
  });
695
759
 
696
760
  describe('createProgrammaticToolCallingTool - Manual Invocation', () => {
@@ -889,11 +953,7 @@ for member in team:
889
953
  });
890
954
  });
891
955
 
892
- it('passes files through on the artifact, never on the LLM-facing output', () => {
893
- /* Output stays stdout/stderr-only regardless of file count or
894
- * filename shape. The artifact is the sole sink for file refs;
895
- * hosts thread them into `_injected_files` on subsequent
896
- * tool calls via `storeCodeSessionFromResults`. */
956
+ it('summarizes files in output while keeping exact refs on the artifact', () => {
897
957
  const response: t.ProgrammaticExecutionResponse = {
898
958
  status: 'completed',
899
959
  stdout: 'Report generated\n',
@@ -909,14 +969,38 @@ for member in team:
909
969
 
910
970
  const [output, artifact] = formatCompletedResponse(response);
911
971
 
912
- expect(output).toBe('stdout:\nReport generated');
972
+ expect(output).toContain('stdout:\nReport generated');
973
+ expect(output).toContain(
974
+ 'Session files: 4 persisted file(s) are available in /mnt/data, including 1 image(s).'
975
+ );
913
976
  expect(output).not.toContain('report.csv');
914
977
  expect(output).not.toContain('chart.png');
915
- expect(output).not.toContain('/mnt/data/');
916
978
 
917
979
  expect(artifact.files).toHaveLength(4);
918
980
  expect(artifact.files).toEqual(response.files);
919
981
  });
982
+
983
+ it('treats malformed file refs as non-image files', () => {
984
+ const malformedFile = { id: 'broken' } as t.FileRef;
985
+ const response: t.ProgrammaticExecutionResponse = {
986
+ status: 'completed',
987
+ stdout: 'Report generated\n',
988
+ stderr: '',
989
+ files: [
990
+ { id: '1', name: 'chart.png' },
991
+ malformedFile,
992
+ { id: '3', name: 'inherited.png', inherited: true },
993
+ ],
994
+ session_id: 'sess_xyz',
995
+ };
996
+
997
+ const [output, artifact] = formatCompletedResponse(response);
998
+
999
+ expect(output).toContain(
1000
+ 'Session files: 2 persisted file(s) are available in /mnt/data, including 1 image(s).'
1001
+ );
1002
+ expect(artifact.files).toEqual(response.files);
1003
+ });
920
1004
  });
921
1005
 
922
1006
  describe('Tool Data Extraction', () => {