fix: упрощение работы с Qwen Code

Изменения:
- Использование флага -p для передачи задачи
- Простой текстовый вывод вместо stream-json
- Каждый запрос запускает новый процесс qwen
- Убрано сложное управление сессиями
- Edit сообщения вместо новых сообщений

Теперь /ai работает стабильнее

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mirivlad 2026-02-24 04:16:41 +08:00
parent 5d451ff870
commit cac597688d
2 changed files with 48 additions and 50 deletions

36
bot.py
View File

@ -2687,41 +2687,33 @@ async def ai_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
return return
# Отправляем задачу в ИИ # Отправляем задачу в ИИ
await update.message.reply_text("⏳ 🤖 Думаю...", parse_mode="Markdown") status_msg = await update.message.reply_text("⏳ 🤖 Думаю...", parse_mode="Markdown")
output_buffer = [] output_buffer = []
oauth_url_sent = False
def on_output(text: str): def on_output(text: str):
output_buffer.append(text) output_buffer.append(text)
def on_oauth_url(url: str): def on_oauth_url(url: str):
nonlocal oauth_url_sent pass # OAuth обрабатывается автоматически при первом запуске
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"
))
# Выполняем задачу # Выполняем задачу
result = await qwen_manager.run_task(user_id, task, on_output, on_oauth_url) 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).strip()
full_output = "".join(output_buffer)
if len(full_output) > 4000: if not full_output:
full_output = full_output[:4000] + "\n... (вывод обрезан)" full_output = result
await update.message.reply_text( if len(full_output) > 4000:
f"🤖 *Результат:*\n\n" full_output = full_output[:4000] + "\n... (вывод обрезан)"
f"```\n{full_output if full_output else result}\n```",
parse_mode="Markdown" await status_msg.edit_text(
) f"🤖 *Результат:*\n\n"
f"```\n{full_output}\n```",
parse_mode="Markdown"
)
def main(): def main():

View File

@ -88,30 +88,17 @@ class QwenCodeManager:
on_oauth_url: Callable[[str], Any]) -> str: on_oauth_url: Callable[[str], Any]) -> str:
""" """
Выполнить задачу в Qwen Code. Выполнить задачу в Qwen Code.
Для простоты каждый раз запускаем новый процесс.
Args:
user_id: ID пользователя
task: Задача для выполнения
on_output: Callback для вывода (вызывается при появлении вывода)
on_oauth_url: Callback для OAuth URL (вызывается если нужна авторизация)
Returns:
Результат выполнения
""" """
# Создаём временную сессию для отслеживания
session = self.get_session(user_id) session = self.get_session(user_id)
if not session:
# Если сессии нет или она в ошибке — создаём новую
if not session or session.state == QwenSessionState.ERROR:
session = self.create_session(user_id) session = self.create_session(user_id)
session.last_activity = datetime.now() session.last_activity = datetime.now()
session.pending_task = task session.pending_task = task
# Если сессия ещё не готова (ожидает OAuth или запуска) # Просто выполняем задачу через -p флаг
if session.state in [QwenSessionState.STARTING, QwenSessionState.WAITING_FOR_OAUTH]:
return await self._start_session(session, on_output, on_oauth_url, task)
# Если сессия готова — выполняем задачу
return await self._execute_task(session, task, on_output) return await self._execute_task(session, task, on_output)
async def _start_session(self, session: QwenSession, async def _start_session(self, session: QwenSession,
@ -208,11 +195,29 @@ class QwenCodeManager:
session.output_buffer = "" session.output_buffer = ""
try: try:
# Отправляем задачу # Для неинтерактивного режима используем -p
session.process.stdin.write(task + "\n") env = os.environ.copy()
session.process.stdin.flush() 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 = "" output = ""
timeout = 300 # 5 минут на выполнение timeout = 300 # 5 минут на выполнение
@ -222,31 +227,32 @@ class QwenCodeManager:
# Проверяем таймаут # Проверяем таймаут
if (datetime.now() - start_time).total_seconds() > timeout: if (datetime.now() - start_time).total_seconds() > timeout:
output += "\n\n⚠️ Таймаут выполнения (5 минут)" output += "\n\n⚠️ Таймаут выполнения (5 минут)"
process.terminate()
break 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: if remaining:
output += remaining output += remaining
on_output(remaining) on_output(remaining)
break break
# Читаем вывод # Читаем вывод
line = session.process.stdout.readline() line = process.stdout.readline()
if line: if line:
output += line output += line
session.output_buffer += line session.output_buffer += line
on_output(line) on_output(line)
# Небольшая пауза чтобы не блокировать # Небольшая пауза
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
session.state = QwenSessionState.READY session.state = QwenSessionState.READY
session.last_activity = datetime.now() session.last_activity = datetime.now()
return self._parse_output(output) return output.strip()
except Exception as e: except Exception as e:
session.state = QwenSessionState.ERROR session.state = QwenSessionState.ERROR