@librechat/agents 3.1.99 → 3.2.1
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.
- package/dist/cjs/graphs/Graph.cjs +154 -67
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +9 -1
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +93 -7
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/stream.cjs +10 -8
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +155 -68
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +9 -1
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +94 -8
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/stream.mjs +10 -8
- package/dist/esm/stream.mjs.map +1 -1
- package/package.json +1 -1
- package/src/graphs/Graph.ts +246 -104
- package/src/graphs/__tests__/Graph.reasoning.test.ts +747 -0
- package/src/langfuse.ts +13 -4
- package/src/messages/core.ts +126 -11
- package/src/messages/formatAgentMessages.test.ts +122 -0
- package/src/specs/deepseek.simple.test.ts +8 -3
- package/src/specs/langfuse-callbacks.test.ts +2 -1
- package/src/specs/langfuse-config.test.ts +23 -0
- package/src/specs/moonshot.simple.test.ts +8 -3
- package/src/splitStream.test.ts +64 -0
- package/src/stream.ts +12 -10
|
@@ -66,6 +66,112 @@ const CALIBRATION_VARIANCE_THRESHOLD = 0.15;
|
|
|
66
66
|
function getHandlerDispatchedEventKey(eventName, stepId) {
|
|
67
67
|
return `${eventName}:${stepId}`;
|
|
68
68
|
}
|
|
69
|
+
function getReasoningText(value) {
|
|
70
|
+
if (typeof value === 'string') {
|
|
71
|
+
return value !== '' ? value : undefined;
|
|
72
|
+
}
|
|
73
|
+
const summaryText = value?.summary
|
|
74
|
+
?.map((summary) => summary.text ?? '')
|
|
75
|
+
.filter((text) => text !== '')
|
|
76
|
+
.join('');
|
|
77
|
+
return summaryText != null && summaryText !== '' ? summaryText : undefined;
|
|
78
|
+
}
|
|
79
|
+
function getReasoningDetailsText(value) {
|
|
80
|
+
if (!Array.isArray(value)) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const reasoningText = value
|
|
84
|
+
.filter((detail) => detail.type === 'reasoning.text')
|
|
85
|
+
.map((detail) => detail.text ?? '')
|
|
86
|
+
.filter((text) => text !== '')
|
|
87
|
+
.join('');
|
|
88
|
+
return reasoningText !== '' ? reasoningText : undefined;
|
|
89
|
+
}
|
|
90
|
+
function getResponseReasoningContent({ responseMessage, reasoningKey, }) {
|
|
91
|
+
const additionalKwargs = responseMessage?.additional_kwargs;
|
|
92
|
+
if (additionalKwargs == null) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const keyedReasoning = getReasoningText(additionalKwargs[reasoningKey]);
|
|
96
|
+
if (keyedReasoning != null) {
|
|
97
|
+
return keyedReasoning;
|
|
98
|
+
}
|
|
99
|
+
const reasoningContent = getReasoningText(additionalKwargs.reasoning_content);
|
|
100
|
+
if (reasoningContent != null) {
|
|
101
|
+
return reasoningContent;
|
|
102
|
+
}
|
|
103
|
+
const reasoning = getReasoningText(additionalKwargs.reasoning);
|
|
104
|
+
if (reasoning != null) {
|
|
105
|
+
return reasoning;
|
|
106
|
+
}
|
|
107
|
+
return getReasoningDetailsText(additionalKwargs.reasoning_details);
|
|
108
|
+
}
|
|
109
|
+
function getTextMessageDeltaContent(content) {
|
|
110
|
+
if (content == null) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (typeof content === 'string') {
|
|
114
|
+
return content !== ''
|
|
115
|
+
? [{ type: _enum.ContentTypes.TEXT, text: content }]
|
|
116
|
+
: undefined;
|
|
117
|
+
}
|
|
118
|
+
if (content.length === 0) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
if (!content.every((contentPart) => typeof contentPart === 'object' &&
|
|
122
|
+
'type' in contentPart &&
|
|
123
|
+
typeof contentPart.type === 'string' &&
|
|
124
|
+
contentPart.type.startsWith('text'))) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
return content;
|
|
128
|
+
}
|
|
129
|
+
async function dispatchTextMessageContent({ graph, stepKey, content, metadata, }) {
|
|
130
|
+
const messageId = ids.getMessageId(stepKey, graph) ?? '';
|
|
131
|
+
if (!messageId) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
await graph.dispatchRunStep(stepKey, {
|
|
135
|
+
type: _enum.StepTypes.MESSAGE_CREATION,
|
|
136
|
+
message_creation: { message_id: messageId },
|
|
137
|
+
}, metadata);
|
|
138
|
+
const stepId = graph.getStepIdByKey(stepKey);
|
|
139
|
+
await graph.dispatchMessageDelta(stepId, { content }, metadata);
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
async function dispatchReasoningContent({ graph, agentContext, reasoningContent, metadata, }) {
|
|
143
|
+
const previousTokenType = agentContext.currentTokenType;
|
|
144
|
+
const previousTokenTypeSwitch = agentContext.tokenTypeSwitch;
|
|
145
|
+
const previousTransitionCount = agentContext.reasoningTransitionCount;
|
|
146
|
+
agentContext.currentTokenType = _enum.ContentTypes.THINK;
|
|
147
|
+
agentContext.tokenTypeSwitch = 'reasoning';
|
|
148
|
+
const stepKey = graph.getStepKey(metadata);
|
|
149
|
+
const messageId = ids.getMessageId(stepKey, graph) ?? '';
|
|
150
|
+
if (!messageId) {
|
|
151
|
+
agentContext.currentTokenType = previousTokenType;
|
|
152
|
+
agentContext.tokenTypeSwitch = previousTokenTypeSwitch;
|
|
153
|
+
agentContext.reasoningTransitionCount = previousTransitionCount;
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
await graph.dispatchRunStep(stepKey, {
|
|
157
|
+
type: _enum.StepTypes.MESSAGE_CREATION,
|
|
158
|
+
message_creation: { message_id: messageId },
|
|
159
|
+
}, metadata);
|
|
160
|
+
const stepId = graph.getStepIdByKey(stepKey);
|
|
161
|
+
await graph.dispatchReasoningDelta(stepId, {
|
|
162
|
+
content: [{ type: _enum.ContentTypes.THINK, think: reasoningContent }],
|
|
163
|
+
}, metadata);
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
function markPostReasoningContent(agentContext) {
|
|
167
|
+
if (agentContext.tokenTypeSwitch !== 'reasoning' ||
|
|
168
|
+
agentContext.currentTokenType === _enum.ContentTypes.TEXT) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
agentContext.currentTokenType = _enum.ContentTypes.TEXT;
|
|
172
|
+
agentContext.tokenTypeSwitch = 'content';
|
|
173
|
+
agentContext.reasoningTransitionCount++;
|
|
174
|
+
}
|
|
69
175
|
class Graph {
|
|
70
176
|
messageStepHasToolCalls = new Map();
|
|
71
177
|
messageIdsByStepKey = new Map();
|
|
@@ -1074,80 +1180,61 @@ class StandardGraph extends Graph {
|
|
|
1074
1180
|
const toolCalls = responseMessage
|
|
1075
1181
|
?.tool_calls;
|
|
1076
1182
|
const hasToolCalls = Array.isArray(toolCalls) && toolCalls.length > 0;
|
|
1183
|
+
const metadata = config.metadata;
|
|
1184
|
+
const responseReasoningContent = getResponseReasoningContent({
|
|
1185
|
+
responseMessage: responseMessage,
|
|
1186
|
+
reasoningKey: agentContext.reasoningKey,
|
|
1187
|
+
});
|
|
1188
|
+
const textMessageContent = getTextMessageDeltaContent(responseMessage?.content);
|
|
1077
1189
|
if (hasToolCalls) {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
if (typeof content === 'string') {
|
|
1099
|
-
await this.dispatchMessageDelta(stepId, {
|
|
1100
|
-
content: [{ type: _enum.ContentTypes.TEXT, text: content }],
|
|
1101
|
-
}, metadata);
|
|
1102
|
-
}
|
|
1103
|
-
else if (Array.isArray(content) &&
|
|
1104
|
-
content.every((c) => typeof c === 'object' &&
|
|
1105
|
-
'type' in c &&
|
|
1106
|
-
typeof c.type === 'string' &&
|
|
1107
|
-
c.type.startsWith('text'))) {
|
|
1108
|
-
await this.dispatchMessageDelta(stepId, {
|
|
1109
|
-
content: content,
|
|
1110
|
-
}, metadata);
|
|
1111
|
-
}
|
|
1190
|
+
const dispatchedReasoning = responseReasoningContent != null &&
|
|
1191
|
+
(await dispatchReasoningContent({
|
|
1192
|
+
graph: this,
|
|
1193
|
+
agentContext,
|
|
1194
|
+
reasoningContent: responseReasoningContent,
|
|
1195
|
+
metadata,
|
|
1196
|
+
}));
|
|
1197
|
+
if (dispatchedReasoning) {
|
|
1198
|
+
markPostReasoningContent(agentContext);
|
|
1199
|
+
}
|
|
1200
|
+
if (textMessageContent != null) {
|
|
1201
|
+
const stepKey = this.getStepKey(metadata);
|
|
1202
|
+
const dispatchedText = await dispatchTextMessageContent({
|
|
1203
|
+
graph: this,
|
|
1204
|
+
stepKey,
|
|
1205
|
+
content: textMessageContent,
|
|
1206
|
+
metadata,
|
|
1207
|
+
});
|
|
1208
|
+
if (dispatchedText) {
|
|
1209
|
+
markPostReasoningContent(agentContext);
|
|
1112
1210
|
}
|
|
1113
1211
|
}
|
|
1114
1212
|
await handlers.handleToolCalls(toolCalls, metadata, this);
|
|
1115
1213
|
}
|
|
1116
1214
|
/**
|
|
1117
|
-
* When streaming
|
|
1118
|
-
*
|
|
1119
|
-
*
|
|
1215
|
+
* When streaming events are unavailable, ChatModelStreamHandler never
|
|
1216
|
+
* fires. Dispatch final reasoning/text content here. getMessageId makes
|
|
1217
|
+
* this a no-op when the streaming path already handled the same step.
|
|
1120
1218
|
*/
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}, metadata);
|
|
1141
|
-
}
|
|
1142
|
-
else if (Array.isArray(content) &&
|
|
1143
|
-
content.every((c) => typeof c === 'object' &&
|
|
1144
|
-
'type' in c &&
|
|
1145
|
-
typeof c.type === 'string' &&
|
|
1146
|
-
c.type.startsWith('text'))) {
|
|
1147
|
-
await this.dispatchMessageDelta(stepId, {
|
|
1148
|
-
content: content,
|
|
1149
|
-
}, metadata);
|
|
1150
|
-
}
|
|
1219
|
+
if (!hasToolCalls && responseMessage != null) {
|
|
1220
|
+
const dispatchedReasoning = responseReasoningContent != null &&
|
|
1221
|
+
(await dispatchReasoningContent({
|
|
1222
|
+
graph: this,
|
|
1223
|
+
agentContext,
|
|
1224
|
+
reasoningContent: responseReasoningContent,
|
|
1225
|
+
metadata,
|
|
1226
|
+
}));
|
|
1227
|
+
if (dispatchedReasoning && textMessageContent != null) {
|
|
1228
|
+
markPostReasoningContent(agentContext);
|
|
1229
|
+
}
|
|
1230
|
+
if (textMessageContent != null) {
|
|
1231
|
+
const stepKey = this.getStepKey(metadata);
|
|
1232
|
+
await dispatchTextMessageContent({
|
|
1233
|
+
graph: this,
|
|
1234
|
+
stepKey,
|
|
1235
|
+
content: textMessageContent,
|
|
1236
|
+
metadata,
|
|
1237
|
+
});
|
|
1151
1238
|
}
|
|
1152
1239
|
}
|
|
1153
1240
|
const invokeElapsed = ((Date.now() - invokeStart) / 1000).toFixed(2);
|