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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-alpha",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Telegram bot for Qwen Code integration — AI-powered code review, bug detection, and code generation",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -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;
@@ -20,9 +20,9 @@ module.exports = {
20
20
  /** Настройки Qwen Code */
21
21
  qwen: {
22
22
  /** Таймаут выполнения команды (мс) */
23
- timeout: parseInt(process.env.QWEN_TIMEOUT, 10) || 60000,
23
+ timeout: parseInt(process.env.QWEN_TIMEOUT, 10) || 120000,
24
24
  /** Максимальный размер буфера (байты) */
25
- maxBuffer: parseInt(process.env.QWEN_MAX_BUFFER, 10) || 2 * 1024 * 1024, // 2MB
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
- // Поиск последнего сообщения от assistant с текстом
164
- const assistantMessages = messages.filter(m => m.type === 'assistant' && m.message?.content);
165
- const lastAssistantMessage = assistantMessages.length > 0
166
- ? assistantMessages[assistantMessages.length - 1]
167
- : null;
168
-
169
- if (lastAssistantMessage?.message?.content) {
170
- const content = lastAssistantMessage.message.content;
171
-
172
- // Content может быть строкой или массивом
173
- if (typeof content === 'string') {
174
- return content;
175
- }
176
-
177
- if (Array.isArray(content)) {
178
- // Поиск текстовой части (может быть thinking + text)
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
- // Поиск result сообщения (fallback)
192
- const resultMessage = messages.find(m => m.type === 'result');
193
- if (resultMessage?.result) {
194
- return resultMessage.result;
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
  }