@wu529778790/open-im 0.3.0 → 0.3.2
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.
|
@@ -29,11 +29,11 @@ class DynamicThrottle {
|
|
|
29
29
|
this.lastUpdate = now;
|
|
30
30
|
return errorDelay;
|
|
31
31
|
}
|
|
32
|
-
//
|
|
32
|
+
// 内容增长较小时,适当增加延迟
|
|
33
33
|
const contentGrowth = contentLength - this.lastContentLength;
|
|
34
|
-
if (contentGrowth <
|
|
34
|
+
if (contentGrowth < 50 && timeSinceLastUpdate < 500) {
|
|
35
35
|
this.lastUpdate = now;
|
|
36
|
-
return
|
|
36
|
+
return 500; // 内容增长缓慢时,每 500ms 更新一次
|
|
37
37
|
}
|
|
38
38
|
// 内容增长较快,使用基础间隔
|
|
39
39
|
this.lastUpdate = now;
|
|
@@ -99,6 +99,9 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
99
99
|
const taskKey = `${userId}:${msgId}`;
|
|
100
100
|
// 创建动态节流器
|
|
101
101
|
const throttle = new DynamicThrottle();
|
|
102
|
+
// 保存思考内容和状态
|
|
103
|
+
let savedThinkingText = '';
|
|
104
|
+
let hasThinkingContent = false; // 是否包含思考内容
|
|
102
105
|
// 创建包装的流式更新函数(带串行化、智能跳过和防抖)
|
|
103
106
|
const createStreamUpdateWrapper = () => {
|
|
104
107
|
let lastUpdateTime = 0;
|
|
@@ -108,8 +111,8 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
108
111
|
let updateInProgress = false; // 串行化锁
|
|
109
112
|
let scheduledContent = null; // 待更新内容
|
|
110
113
|
let scheduledToolNote;
|
|
111
|
-
//
|
|
112
|
-
const STREAM_PREVIEW_LENGTH =
|
|
114
|
+
// 流式输出时显示最后 N 个字符(增加到 1500 以提高流畅度)
|
|
115
|
+
const STREAM_PREVIEW_LENGTH = 1500;
|
|
113
116
|
// 执行更新(串行化)
|
|
114
117
|
const performUpdate = async (content, toolNote) => {
|
|
115
118
|
if (updateInProgress) {
|
|
@@ -120,10 +123,40 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
120
123
|
}
|
|
121
124
|
updateInProgress = true;
|
|
122
125
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
let displayContent = content;
|
|
127
|
+
// 如果有思考内容,将其格式化后添加到前面
|
|
128
|
+
if (hasThinkingContent && savedThinkingText) {
|
|
129
|
+
// 思考内容使用引用格式,用分隔线区分
|
|
130
|
+
const thinkingFormatted = `💭 思考过程:\n${savedThinkingText}`;
|
|
131
|
+
const separator = '\n\n─────────\n\n';
|
|
132
|
+
// 组合内容
|
|
133
|
+
const combined = thinkingFormatted + separator + content;
|
|
134
|
+
// 如果组合后超过预览长度,截取最后部分(但保留思考内容)
|
|
135
|
+
if (combined.length > STREAM_PREVIEW_LENGTH) {
|
|
136
|
+
// 如果思考内容本身就很长,截取思考内容
|
|
137
|
+
const maxThinkingLength = 800;
|
|
138
|
+
const truncatedThinking = savedThinkingText.length > maxThinkingLength
|
|
139
|
+
? `...(已省略 ${savedThinkingText.length - maxThinkingLength} 字符)...\n\n${savedThinkingText.slice(-maxThinkingLength)}`
|
|
140
|
+
: savedThinkingText;
|
|
141
|
+
displayContent = `💭 思考过程:\n${truncatedThinking}\n\n─────────\n\n`;
|
|
142
|
+
// 添加输出内容的最后部分
|
|
143
|
+
if (content.length > 800) {
|
|
144
|
+
displayContent += `...\n\n${content.slice(-800)}`;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
displayContent += content;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
displayContent = combined;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// 没有思考内容,直接显示(如果超过预览长度则截取)
|
|
156
|
+
displayContent = content.length > STREAM_PREVIEW_LENGTH
|
|
157
|
+
? `...\n\n${content.slice(-STREAM_PREVIEW_LENGTH)}`
|
|
158
|
+
: content;
|
|
159
|
+
}
|
|
127
160
|
const note = toolNote ? '输出中...\n' + toolNote : '输出中...';
|
|
128
161
|
await updateMessage(chatId, msgId, displayContent, 'streaming', note, toolId);
|
|
129
162
|
throttle.recordSuccess();
|
|
@@ -144,15 +177,21 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
144
177
|
}
|
|
145
178
|
}
|
|
146
179
|
};
|
|
147
|
-
//
|
|
148
|
-
const DEBOUNCE_MS =
|
|
180
|
+
// 防抖延迟(毫秒)- 降低到 150ms 提高响应速度
|
|
181
|
+
const DEBOUNCE_MS = 150;
|
|
149
182
|
let debounceTimer = null;
|
|
150
183
|
return (content, toolNote) => {
|
|
184
|
+
// 检测是否是思考内容
|
|
185
|
+
if (content.startsWith('💭 **思考中...**')) {
|
|
186
|
+
// 保存思考内容(去掉前缀)
|
|
187
|
+
savedThinkingText = content.replace('💭 **思考中...**\n\n', '');
|
|
188
|
+
hasThinkingContent = true;
|
|
189
|
+
}
|
|
151
190
|
const now = Date.now();
|
|
152
191
|
const elapsed = now - lastUpdateTime;
|
|
153
|
-
// 智能跳过:内容增长小于
|
|
192
|
+
// 智能跳过:内容增长小于 30 字符且距离上次更新不足 500ms(降低阈值,提高流畅度)
|
|
154
193
|
const contentGrowth = content.length - lastContentLength;
|
|
155
|
-
if (contentGrowth <
|
|
194
|
+
if (contentGrowth < 30 && elapsed < 500 && lastContentLength > 0) {
|
|
156
195
|
// 跳过此次更新,但更新长度记录
|
|
157
196
|
lastContentLength = content.length;
|
|
158
197
|
lastContent = content;
|
|
@@ -178,9 +217,21 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
178
217
|
await runAITask({ config, sessionManager }, { userId, chatId, workDir, sessionId, convId, platform: 'telegram', taskKey }, prompt, toolAdapter, {
|
|
179
218
|
throttleMs: THROTTLE_MS,
|
|
180
219
|
streamUpdate: streamUpdateWrapper,
|
|
220
|
+
onThinkingToText: (content) => {
|
|
221
|
+
// 从思考转到文本输出时,标记有思考内容
|
|
222
|
+
// 注意:此时不保存文本内容,因为后续会通过 streamUpdate 持续更新
|
|
223
|
+
},
|
|
181
224
|
sendComplete: async (content, note) => {
|
|
182
225
|
throttle.reset();
|
|
183
|
-
|
|
226
|
+
// 完成时,如果有思考内容,将其包含在最终消息中
|
|
227
|
+
if (savedThinkingText && hasThinkingContent) {
|
|
228
|
+
const thinkingFormatted = `💭 思考过程:\n${savedThinkingText}\n\n─────────\n\n`;
|
|
229
|
+
const combined = thinkingFormatted + content;
|
|
230
|
+
await sendFinalMessages(chatId, msgId, combined, note, toolId);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
await sendFinalMessages(chatId, msgId, content, note, toolId);
|
|
234
|
+
}
|
|
184
235
|
},
|
|
185
236
|
sendError: async (error) => {
|
|
186
237
|
throttle.reset();
|
|
@@ -188,6 +239,9 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
188
239
|
},
|
|
189
240
|
extraCleanup: () => {
|
|
190
241
|
throttle.reset();
|
|
242
|
+
// 清理思考内容
|
|
243
|
+
savedThinkingText = '';
|
|
244
|
+
hasThinkingContent = false;
|
|
191
245
|
stopTyping();
|
|
192
246
|
runningTasks.delete(taskKey);
|
|
193
247
|
},
|
|
@@ -105,8 +105,8 @@ export async function updateMessage(chatId, messageId, content, status, note, to
|
|
|
105
105
|
opts.reply_markup = buildStopKeyboard(Number(messageId));
|
|
106
106
|
}
|
|
107
107
|
else if (status === 'done' || status === 'error') {
|
|
108
|
-
//
|
|
109
|
-
opts.reply_markup = {};
|
|
108
|
+
// 完成或错误时,显式移除停止按钮(使用空的 inline_keyboard)
|
|
109
|
+
opts.reply_markup = { inline_keyboard: [] };
|
|
110
110
|
}
|
|
111
111
|
// 流式输出时使用纯文本,避免 Markdown 解析导致内容减少
|
|
112
112
|
// 只在完成时应用 Markdown 格式
|