From cac597688d76df6d1658617c8c27ad18d3e24197 Mon Sep 17 00:00:00 2001 From: mirivlad Date: Tue, 24 Feb 2026 04:16:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=83=D0=BF=D1=80=D0=BE=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20Qwen=20Code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Изменения: - Использование флага -p для передачи задачи - Простой текстовый вывод вместо stream-json - Каждый запрос запускает новый процесс qwen - Убрано сложное управление сессиями - Edit сообщения вместо новых сообщений Теперь /ai работает стабильнее Co-authored-by: Qwen-Coder --- bot.py | 40 +++++++++++++------------------ qwen_integration.py | 58 +++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/bot.py b/bot.py index 1677b39..dc387f1 100644 --- a/bot.py +++ b/bot.py @@ -2687,41 +2687,33 @@ async def ai_command(update: Update, context: ContextTypes.DEFAULT_TYPE): return # Отправляем задачу в ИИ - await update.message.reply_text("⏳ 🤖 Думаю...", parse_mode="Markdown") + status_msg = await update.message.reply_text("⏳ 🤖 Думаю...", parse_mode="Markdown") output_buffer = [] - oauth_url_sent = False def on_output(text: str): output_buffer.append(text) def on_oauth_url(url: str): - nonlocal oauth_url_sent - if not oauth_url_sent: - oauth_url_sent = True - asyncio.create_task(update.message.reply_text( - f"🔐 *Требуется авторизация Qwen Code*\n\n" - f"Откройте ссылку для авторизации:\n" - f"{url}\n\n" - f"После авторизации отправьте команду снова.", - parse_mode="Markdown" - )) + pass # OAuth обрабатывается автоматически при первом запуске # Выполняем задачу result = await qwen_manager.run_task(user_id, task, on_output, on_oauth_url) - # Если это не OAuth — показываем результат - if not oauth_url_sent: - full_output = "".join(output_buffer) - - if len(full_output) > 4000: - full_output = full_output[:4000] + "\n... (вывод обрезан)" - - await update.message.reply_text( - f"🤖 *Результат:*\n\n" - f"```\n{full_output if full_output else result}\n```", - parse_mode="Markdown" - ) + # Показываем результат + full_output = "".join(output_buffer).strip() + + if not full_output: + full_output = result + + if len(full_output) > 4000: + full_output = full_output[:4000] + "\n... (вывод обрезан)" + + await status_msg.edit_text( + f"🤖 *Результат:*\n\n" + f"```\n{full_output}\n```", + parse_mode="Markdown" + ) def main(): diff --git a/qwen_integration.py b/qwen_integration.py index aea1942..4b4e22f 100644 --- a/qwen_integration.py +++ b/qwen_integration.py @@ -88,30 +88,17 @@ class QwenCodeManager: on_oauth_url: Callable[[str], Any]) -> str: """ Выполнить задачу в Qwen Code. - - Args: - user_id: ID пользователя - task: Задача для выполнения - on_output: Callback для вывода (вызывается при появлении вывода) - on_oauth_url: Callback для OAuth URL (вызывается если нужна авторизация) - - Returns: - Результат выполнения + Для простоты каждый раз запускаем новый процесс. """ + # Создаём временную сессию для отслеживания session = self.get_session(user_id) - - # Если сессии нет или она в ошибке — создаём новую - if not session or session.state == QwenSessionState.ERROR: + if not session: session = self.create_session(user_id) session.last_activity = datetime.now() session.pending_task = task - # Если сессия ещё не готова (ожидает OAuth или запуска) - if session.state in [QwenSessionState.STARTING, QwenSessionState.WAITING_FOR_OAUTH]: - return await self._start_session(session, on_output, on_oauth_url, task) - - # Если сессия готова — выполняем задачу + # Просто выполняем задачу через -p флаг return await self._execute_task(session, task, on_output) async def _start_session(self, session: QwenSession, @@ -208,11 +195,29 @@ class QwenCodeManager: session.output_buffer = "" try: - # Отправляем задачу - session.process.stdin.write(task + "\n") - session.process.stdin.flush() + # Для неинтерактивного режима используем -p + env = os.environ.copy() + env["FORCE_COLOR"] = "0" - # Читаем ответ + cmd = [ + self._qwen_command, + "-p", task, # Передаём задачу через флаг -p + "--output-format", "text", # Простой текстовый вывод + ] + + logger.info(f"Выполнение задачи: {' '.join(cmd)}") + + process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=self._working_dir, + env=env, + text=True, + bufsize=1 + ) + + # Читаем вывод output = "" timeout = 300 # 5 минут на выполнение @@ -222,31 +227,32 @@ class QwenCodeManager: # Проверяем таймаут if (datetime.now() - start_time).total_seconds() > timeout: output += "\n\n⚠️ Таймаут выполнения (5 минут)" + process.terminate() break # Проверяем процесс - if session.process.poll() is not None: + if process.poll() is not None: # Процесс завершился - remaining = session.process.stdout.read() + remaining = process.stdout.read() if remaining: output += remaining on_output(remaining) break # Читаем вывод - line = session.process.stdout.readline() + line = process.stdout.readline() if line: output += line session.output_buffer += line on_output(line) - # Небольшая пауза чтобы не блокировать + # Небольшая пауза await asyncio.sleep(0.1) session.state = QwenSessionState.READY session.last_activity = datetime.now() - return self._parse_output(output) + return output.strip() except Exception as e: session.state = QwenSessionState.ERROR