@librechat/agents 3.3.9 → 3.3.11

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 (61) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +4 -0
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +21 -2
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/langfuseToolOutputTracing.cjs +228 -16
  6. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  7. package/dist/cjs/llm/init.cjs +1 -1
  8. package/dist/cjs/llm/invoke.cjs +14 -7
  9. package/dist/cjs/llm/invoke.cjs.map +1 -1
  10. package/dist/cjs/llm/openai/index.cjs +188 -11
  11. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  12. package/dist/cjs/main.cjs +4 -3
  13. package/dist/cjs/messages/core.cjs +592 -27
  14. package/dist/cjs/messages/core.cjs.map +1 -1
  15. package/dist/cjs/run.cjs +11 -1
  16. package/dist/cjs/run.cjs.map +1 -1
  17. package/dist/cjs/stream.cjs +2 -2
  18. package/dist/cjs/tools/ToolNode.cjs +1 -1
  19. package/dist/cjs/tools/search/tool.cjs +1 -1
  20. package/dist/cjs/utils/index.cjs +1 -1
  21. package/dist/esm/agents/AgentContext.mjs +4 -0
  22. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  23. package/dist/esm/graphs/Graph.mjs +21 -2
  24. package/dist/esm/graphs/Graph.mjs.map +1 -1
  25. package/dist/esm/langfuseToolOutputTracing.mjs +228 -16
  26. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  27. package/dist/esm/llm/init.mjs +1 -1
  28. package/dist/esm/llm/invoke.mjs +14 -7
  29. package/dist/esm/llm/invoke.mjs.map +1 -1
  30. package/dist/esm/llm/openai/index.mjs +190 -13
  31. package/dist/esm/llm/openai/index.mjs.map +1 -1
  32. package/dist/esm/main.mjs +5 -5
  33. package/dist/esm/messages/core.mjs +592 -28
  34. package/dist/esm/messages/core.mjs.map +1 -1
  35. package/dist/esm/run.mjs +11 -1
  36. package/dist/esm/run.mjs.map +1 -1
  37. package/dist/esm/stream.mjs +2 -2
  38. package/dist/esm/tools/ToolNode.mjs +1 -1
  39. package/dist/esm/tools/search/tool.mjs +1 -1
  40. package/dist/esm/utils/index.mjs +1 -1
  41. package/dist/types/agents/AgentContext.d.ts +2 -0
  42. package/dist/types/graphs/Graph.d.ts +5 -0
  43. package/dist/types/langfuseToolOutputTracing.d.ts +1 -0
  44. package/dist/types/llm/invoke.d.ts +1 -1
  45. package/dist/types/messages/core.d.ts +11 -6
  46. package/dist/types/run.d.ts +7 -0
  47. package/package.json +1 -1
  48. package/src/agents/AgentContext.ts +5 -0
  49. package/src/graphs/Graph.ts +39 -0
  50. package/src/langfuseToolOutputTracing.ts +410 -14
  51. package/src/llm/custom-chat-models.smoke.test.ts +747 -0
  52. package/src/llm/invoke.test.ts +98 -0
  53. package/src/llm/invoke.ts +34 -23
  54. package/src/llm/openai/index.ts +334 -25
  55. package/src/llm/openai/llm.spec.ts +107 -6
  56. package/src/messages/core.ts +1290 -42
  57. package/src/messages/formatAgentMessages.test.ts +2623 -0
  58. package/src/run.ts +15 -0
  59. package/src/specs/discovered-tools.test.ts +217 -0
  60. package/src/specs/langfuse-tool-output-tracing.test.ts +887 -0
  61. package/src/specs/preemptSeal.test.ts +374 -5
@@ -82,6 +82,17 @@ type CompletionsStreamDelegate = {
82
82
  ) => AsyncGenerator<ChatGenerationChunk>;
83
83
  };
84
84
 
85
+ type ResponsesStreamDelegate = {
86
+ completionWithRetry: (
87
+ request: OpenAIClient.Responses.ResponseCreateParamsStreaming
88
+ ) => Promise<AsyncIterable<OpenAIClient.Responses.ResponseStreamEvent>>;
89
+ _streamResponseChunks: (
90
+ messages: BaseMessage[],
91
+ options: Record<string, unknown>,
92
+ runManager?: CallbackManagerForLLMRun
93
+ ) => AsyncGenerator<ChatGenerationChunk>;
94
+ };
95
+
85
96
  type InvocationParamsDelegate = {
86
97
  invocationParams: (
87
98
  options: Record<string, unknown>,
@@ -109,6 +120,9 @@ function completionsDelegateOf(model: ChatOpenAI): CompletionsDelegate {
109
120
  const completionsOf = <T>(model: ChatOpenAI): T =>
110
121
  (model as unknown as { completions: T }).completions;
111
122
 
123
+ const responsesOf = <T>(model: ChatOpenAI): T =>
124
+ (model as unknown as { responses: T }).responses;
125
+
112
126
  function newOpenAI(): ChatOpenAI {
113
127
  return new ChatOpenAI({ model: 'gpt-4o-mini', apiKey: 'test-key' });
114
128
  }
@@ -1080,6 +1094,90 @@ describe('ChatOpenAICompletions streaming usage_metadata callback', () => {
1080
1094
  });
1081
1095
  });
1082
1096
 
1097
+ describe('ChatOpenAIResponses streaming callback dispatch', () => {
1098
+ it('emits the callback before a consumer stops at the yielded chunk', async () => {
1099
+ const model = new ChatOpenAI({
1100
+ model: 'gpt-5',
1101
+ apiKey: 'test-key',
1102
+ useResponsesApi: true,
1103
+ });
1104
+ const responses = responsesOf<ResponsesStreamDelegate>(model);
1105
+ responses.completionWithRetry = async () =>
1106
+ (async function* () {
1107
+ yield {
1108
+ type: 'response.output_text.delta',
1109
+ sequence_number: 0,
1110
+ output_index: 0,
1111
+ content_index: 0,
1112
+ item_id: 'msg_callback',
1113
+ delta: 'visible chunk',
1114
+ logprobs: [],
1115
+ } as OpenAIClient.Responses.ResponseStreamEvent;
1116
+ })();
1117
+
1118
+ const events: string[] = [];
1119
+ const runManager = {
1120
+ handleLLMNewToken(token: string): void {
1121
+ events.push(`callback:${token}`);
1122
+ },
1123
+ } as unknown as CallbackManagerForLLMRun;
1124
+
1125
+ for await (const chunk of responses._streamResponseChunks(
1126
+ [new HumanMessage('test')],
1127
+ {},
1128
+ runManager
1129
+ )) {
1130
+ events.push(`yield:${chunk.text}`);
1131
+ break;
1132
+ }
1133
+
1134
+ expect(events).toEqual(['callback:visible chunk', 'yield:visible chunk']);
1135
+ });
1136
+
1137
+ it('propagates an abort received with the next buffered event', async () => {
1138
+ const model = new ChatOpenAI({
1139
+ model: 'gpt-5',
1140
+ apiKey: 'test-key',
1141
+ useResponsesApi: true,
1142
+ });
1143
+ const responses = responsesOf<ResponsesStreamDelegate>(model);
1144
+ const controller = new AbortController();
1145
+ const abortReason = new Error('buffered Responses stream aborted');
1146
+ responses.completionWithRetry = async () =>
1147
+ (async function* () {
1148
+ yield {
1149
+ type: 'response.output_text.delta',
1150
+ sequence_number: 0,
1151
+ output_index: 0,
1152
+ content_index: 0,
1153
+ item_id: 'msg_abort',
1154
+ delta: 'partial',
1155
+ logprobs: [],
1156
+ } as OpenAIClient.Responses.ResponseStreamEvent;
1157
+ controller.abort(abortReason);
1158
+ yield {
1159
+ type: 'response.output_text.delta',
1160
+ sequence_number: 1,
1161
+ output_index: 0,
1162
+ content_index: 0,
1163
+ item_id: 'msg_abort',
1164
+ delta: ' must not complete normally',
1165
+ logprobs: [],
1166
+ } as OpenAIClient.Responses.ResponseStreamEvent;
1167
+ })();
1168
+
1169
+ const stream = responses._streamResponseChunks([new HumanMessage('test')], {
1170
+ signal: controller.signal,
1171
+ });
1172
+
1173
+ await expect(stream.next()).resolves.toMatchObject({
1174
+ done: false,
1175
+ value: { text: 'partial' },
1176
+ });
1177
+ await expect(stream.next()).rejects.toBe(abortReason);
1178
+ });
1179
+ });
1180
+
1083
1181
  describe('ChatOpenAICompletions reasoning_content compatibility', () => {
1084
1182
  it('should preserve reasoning_content on streamed assistant chunks', async () => {
1085
1183
  const model = new ChatOpenAI({
@@ -1237,11 +1335,15 @@ describe('ChatOpenAICompletions strict tools for structured output', () => {
1237
1335
  }) as unknown as {
1238
1336
  tools?: { function: { parameters: { properties: object } } }[];
1239
1337
  };
1240
- return Object.keys(params.tools?.[0]?.function.parameters.properties ?? {});
1338
+ return Object.keys(
1339
+ params.tools?.[0]?.function.parameters.properties ?? {}
1340
+ );
1241
1341
  }
1242
1342
 
1243
1343
  it('drops the optional label when strict is auto-enabled (invalid otherwise)', () => {
1244
- expect(toolProperties({ response_format: jsonSchemaResponseFormat })).toEqual(['query']);
1344
+ expect(
1345
+ toolProperties({ response_format: jsonSchemaResponseFormat })
1346
+ ).toEqual(['query']);
1245
1347
  });
1246
1348
 
1247
1349
  it('keeps the label on non-strict requests', () => {
@@ -1305,10 +1407,9 @@ describe('ChatOpenAICompletions strict tools for structured output', () => {
1305
1407
  }) as unknown as {
1306
1408
  tools?: { function: { parameters: { properties: object } } }[];
1307
1409
  };
1308
- expect(Object.keys(params.tools?.[0]?.function.parameters.properties ?? {})).toEqual([
1309
- 'intent',
1310
- 'title',
1311
- ]);
1410
+ expect(
1411
+ Object.keys(params.tools?.[0]?.function.parameters.properties ?? {})
1412
+ ).toEqual(['intent', 'title']);
1312
1413
  });
1313
1414
  });
1314
1415
  });