qwen-alpha 1.0.8 → 1.0.10
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/package.json +1 -1
- package/src/bot/handlers/message.js +49 -7
- package/src/config/index.js +2 -2
- package/src/services/qwenService.js +38 -29
package/package.json
CHANGED
|
@@ -95,14 +95,20 @@ async function messageHandler(ctx) {
|
|
|
95
95
|
|
|
96
96
|
// Отправка ответа
|
|
97
97
|
if (loadingMsgId) {
|
|
98
|
-
// Удаляем сообщение "⏳ Думаю..."
|
|
99
|
-
await ctx.telegram.deleteMessage(ctx.chat.id, loadingMsgId);
|
|
98
|
+
// Удаляем сообщение "⏳ Думаю..."
|
|
99
|
+
await ctx.telegram.deleteMessage(ctx.chat.id, loadingMsgId).catch(() => {});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Разбивка длинного ответа на части (Telegram лимит 4096 символов)
|
|
103
|
+
const maxMessageLength = 4000;
|
|
104
|
+
const chunks = splitMessage(responseText, maxMessageLength);
|
|
105
|
+
|
|
106
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
107
|
+
await ctx.reply(chunks[i], {
|
|
108
|
+
parse_mode: 'Markdown',
|
|
109
|
+
reply_parameters: { message_id: ctx.message.message_id },
|
|
110
|
+
});
|
|
100
111
|
}
|
|
101
|
-
|
|
102
|
-
await ctx.reply(responseText, {
|
|
103
|
-
parse_mode: 'Markdown',
|
|
104
|
-
reply_parameters: { message_id: ctx.message.message_id },
|
|
105
|
-
});
|
|
106
112
|
|
|
107
113
|
// Добавление сообщений в сессию
|
|
108
114
|
if (session) {
|
|
@@ -142,4 +148,40 @@ async function messageHandler(ctx) {
|
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Разбиение длинного сообщения на части
|
|
153
|
+
* @param {string} text - Текст для разбиения
|
|
154
|
+
* @param {number} maxLength - Максимальная длина
|
|
155
|
+
* @returns {string[]} Массив частей
|
|
156
|
+
*/
|
|
157
|
+
function splitMessage(text, maxLength) {
|
|
158
|
+
const chunks = [];
|
|
159
|
+
|
|
160
|
+
if (text.length <= maxLength) {
|
|
161
|
+
return [text];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let remaining = text;
|
|
165
|
+
|
|
166
|
+
while (remaining.length > maxLength) {
|
|
167
|
+
// Ищем ближайший перенос строки или пробел
|
|
168
|
+
let splitIndex = remaining.lastIndexOf('\n', maxLength);
|
|
169
|
+
if (splitIndex === -1 || splitIndex < maxLength / 2) {
|
|
170
|
+
splitIndex = remaining.lastIndexOf(' ', maxLength);
|
|
171
|
+
}
|
|
172
|
+
if (splitIndex === -1) {
|
|
173
|
+
splitIndex = maxLength;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
chunks.push(remaining.substring(0, splitIndex));
|
|
177
|
+
remaining = remaining.substring(splitIndex).trim();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (remaining.length > 0) {
|
|
181
|
+
chunks.push(remaining);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return chunks;
|
|
185
|
+
}
|
|
186
|
+
|
|
145
187
|
module.exports = messageHandler;
|
package/src/config/index.js
CHANGED
|
@@ -20,9 +20,9 @@ module.exports = {
|
|
|
20
20
|
/** Настройки Qwen Code */
|
|
21
21
|
qwen: {
|
|
22
22
|
/** Таймаут выполнения команды (мс) */
|
|
23
|
-
timeout: parseInt(process.env.QWEN_TIMEOUT, 10) ||
|
|
23
|
+
timeout: parseInt(process.env.QWEN_TIMEOUT, 10) || 120000,
|
|
24
24
|
/** Максимальный размер буфера (байты) */
|
|
25
|
-
maxBuffer: parseInt(process.env.QWEN_MAX_BUFFER, 10) ||
|
|
25
|
+
maxBuffer: parseInt(process.env.QWEN_MAX_BUFFER, 10) || 10 * 1024 * 1024, // 10MB
|
|
26
26
|
/** Максимальный размер файла для анализа (байты) */
|
|
27
27
|
maxFileSize: 2 * 1024 * 1024, // 2MB
|
|
28
28
|
},
|
|
@@ -160,45 +160,54 @@ class QwenService {
|
|
|
160
160
|
return stdout.trim();
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
// Поиск
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const textPart = content.find(part => part.type === 'text');
|
|
180
|
-
if (textPart?.text) {
|
|
181
|
-
return textPart.text;
|
|
163
|
+
// Поиск всех сообщений от assistant с текстом
|
|
164
|
+
const textContents = [];
|
|
165
|
+
|
|
166
|
+
for (const msg of messages) {
|
|
167
|
+
if (msg.type === 'assistant' && msg.message?.content) {
|
|
168
|
+
const content = msg.message.content;
|
|
169
|
+
|
|
170
|
+
if (Array.isArray(content)) {
|
|
171
|
+
// Ищем текстовые части
|
|
172
|
+
for (const part of content) {
|
|
173
|
+
if (part.type === 'text' && part.text) {
|
|
174
|
+
textContents.push(part.text);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} else if (typeof content === 'string') {
|
|
178
|
+
textContents.push(content);
|
|
182
179
|
}
|
|
183
|
-
// Fallback: объединение всех текстовых частей
|
|
184
|
-
return content
|
|
185
|
-
.filter(part => part.type === 'text')
|
|
186
|
-
.map(part => part.text)
|
|
187
|
-
.join('\n');
|
|
188
180
|
}
|
|
181
|
+
|
|
182
|
+
// Также проверяем result сообщение
|
|
183
|
+
if (msg.type === 'result' && msg.result) {
|
|
184
|
+
textContents.push(msg.result);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Если нашли текст — возвращаем
|
|
189
|
+
if (textContents.length > 0) {
|
|
190
|
+
return textContents.join('\n\n');
|
|
189
191
|
}
|
|
190
192
|
|
|
191
|
-
//
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
194
|
-
|
|
193
|
+
// Fallback: если нет текста, пробуем извлечь информацию из tool_use
|
|
194
|
+
const toolMessages = messages.filter(m => m.type === 'assistant' && m.message?.content?.some(c => c.type === 'tool_use'));
|
|
195
|
+
if (toolMessages.length > 0) {
|
|
196
|
+
const toolInfo = toolMessages.map(m => {
|
|
197
|
+
const tools = m.message.content.filter(c => c.type === 'tool_use');
|
|
198
|
+
return tools.map(t => `Использует инструмент: ${t.name}`).join('; ');
|
|
199
|
+
}).join('. ');
|
|
200
|
+
|
|
201
|
+
if (toolInfo) {
|
|
202
|
+
return `Qwen анализирует: ${toolInfo}. Пожалуйста, уточните запрос для получения текстового ответа.`;
|
|
203
|
+
}
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
// Fallback: возврат всего stdout
|
|
198
207
|
return stdout.trim();
|
|
199
208
|
|
|
200
209
|
} catch (parseError) {
|
|
201
|
-
logger.warn({ parseError, stdout }, 'Failed to parse Qwen JSON response');
|
|
210
|
+
logger.warn({ parseError, stdout: stdout?.substring(0, 500) }, 'Failed to parse Qwen JSON response');
|
|
202
211
|
return stdout.trim();
|
|
203
212
|
}
|
|
204
213
|
}
|