vibego 0.2.52__py3-none-any.whl → 0.2.54__py3-none-any.whl
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.
Potentially problematic release.
This version of vibego might be problematic. Click here for more details.
- bot.py +18 -419
- {vibego-0.2.52.dist-info → vibego-0.2.54.dist-info}/METADATA +1 -1
- {vibego-0.2.52.dist-info → vibego-0.2.54.dist-info}/RECORD +7 -7
- vibego_cli/__init__.py +1 -1
- {vibego-0.2.52.dist-info → vibego-0.2.54.dist-info}/WHEEL +0 -0
- {vibego-0.2.52.dist-info → vibego-0.2.54.dist-info}/entry_points.txt +0 -0
- {vibego-0.2.52.dist-info → vibego-0.2.54.dist-info}/top_level.txt +0 -0
bot.py
CHANGED
|
@@ -37,8 +37,6 @@ from aiogram.types import (
|
|
|
37
37
|
ReplyKeyboardRemove,
|
|
38
38
|
Update,
|
|
39
39
|
User,
|
|
40
|
-
PhotoSize,
|
|
41
|
-
Document,
|
|
42
40
|
)
|
|
43
41
|
from aiogram.client.session.aiohttp import AiohttpSession
|
|
44
42
|
from aiogram.enums import ParseMode
|
|
@@ -87,15 +85,6 @@ def load_env(p: str = ".env"):
|
|
|
87
85
|
|
|
88
86
|
load_env()
|
|
89
87
|
|
|
90
|
-
# 导入媒体处理器
|
|
91
|
-
try:
|
|
92
|
-
from media_handler import MediaHandler, MediaConfig
|
|
93
|
-
HAS_MEDIA_HANDLER = True
|
|
94
|
-
except ImportError:
|
|
95
|
-
HAS_MEDIA_HANDLER = False
|
|
96
|
-
MediaHandler = None
|
|
97
|
-
MediaConfig = None
|
|
98
|
-
|
|
99
88
|
# --- 日志 & 上下文 ---
|
|
100
89
|
PROJECT_NAME = os.environ.get("PROJECT_NAME", "").strip()
|
|
101
90
|
ACTIVE_MODEL = (os.environ.get("ACTIVE_MODEL") or os.environ.get("MODEL_NAME") or "").strip()
|
|
@@ -1171,7 +1160,6 @@ async def _push_task_to_model(
|
|
|
1171
1160
|
supplement: Optional[str],
|
|
1172
1161
|
actor: Optional[str],
|
|
1173
1162
|
is_bug_report: bool = False,
|
|
1174
|
-
media_files: Optional[List[Dict[str, Any]]] = None,
|
|
1175
1163
|
) -> tuple[bool, str, Optional[Path]]:
|
|
1176
1164
|
"""推送任务信息到模型,并附带补充描述。
|
|
1177
1165
|
|
|
@@ -1182,30 +1170,17 @@ async def _push_task_to_model(
|
|
|
1182
1170
|
supplement: 补充描述
|
|
1183
1171
|
actor: 操作者
|
|
1184
1172
|
is_bug_report: 是否为缺陷报告推送
|
|
1185
|
-
media_files: 媒体文件列表
|
|
1186
1173
|
"""
|
|
1187
1174
|
|
|
1188
1175
|
history_text, history_count = await _build_history_context_for_model(task.id)
|
|
1189
1176
|
notes = await TASK_SERVICE.list_notes(task.id)
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
notes=notes,
|
|
1198
|
-
media_files=media_files,
|
|
1199
|
-
is_bug_report=is_bug_report,
|
|
1200
|
-
)
|
|
1201
|
-
else:
|
|
1202
|
-
prompt = _build_model_push_payload(
|
|
1203
|
-
task,
|
|
1204
|
-
supplement=supplement,
|
|
1205
|
-
history=history_text,
|
|
1206
|
-
notes=notes,
|
|
1207
|
-
is_bug_report=is_bug_report,
|
|
1208
|
-
)
|
|
1177
|
+
prompt = _build_model_push_payload(
|
|
1178
|
+
task,
|
|
1179
|
+
supplement=supplement,
|
|
1180
|
+
history=history_text,
|
|
1181
|
+
notes=notes,
|
|
1182
|
+
is_bug_report=is_bug_report,
|
|
1183
|
+
)
|
|
1209
1184
|
success, session_path = await _dispatch_prompt_to_model(
|
|
1210
1185
|
chat_id,
|
|
1211
1186
|
prompt,
|
|
@@ -2023,57 +1998,6 @@ def _build_model_push_payload(
|
|
|
2023
1998
|
return _strip_legacy_bug_header(result or body)
|
|
2024
1999
|
|
|
2025
2000
|
|
|
2026
|
-
def _build_model_push_payload_with_media(
|
|
2027
|
-
task: TaskRecord,
|
|
2028
|
-
supplement: Optional[str] = None,
|
|
2029
|
-
history: Optional[str] = None,
|
|
2030
|
-
notes: Optional[Sequence[TaskNoteRecord]] = None,
|
|
2031
|
-
media_files: Optional[List[Dict[str, Any]]] = None,
|
|
2032
|
-
is_bug_report: bool = False,
|
|
2033
|
-
) -> str:
|
|
2034
|
-
"""构造包含媒体文件引用的模型推送 payload"""
|
|
2035
|
-
|
|
2036
|
-
# 先构造基础 payload
|
|
2037
|
-
base_payload = _build_model_push_payload(
|
|
2038
|
-
task=task,
|
|
2039
|
-
supplement=supplement,
|
|
2040
|
-
history=history,
|
|
2041
|
-
notes=notes,
|
|
2042
|
-
is_bug_report=is_bug_report
|
|
2043
|
-
)
|
|
2044
|
-
|
|
2045
|
-
# 如果没有媒体文件,直接返回
|
|
2046
|
-
if not media_files:
|
|
2047
|
-
return base_payload
|
|
2048
|
-
|
|
2049
|
-
# 添加媒体文件信息
|
|
2050
|
-
lines = [base_payload]
|
|
2051
|
-
lines.append("\n相关文件:")
|
|
2052
|
-
|
|
2053
|
-
for idx, media in enumerate(media_files, 1):
|
|
2054
|
-
file_type = media["type"]
|
|
2055
|
-
file_path = media["file_path"]
|
|
2056
|
-
|
|
2057
|
-
if file_type == "image":
|
|
2058
|
-
width = media.get("width", "?")
|
|
2059
|
-
height = media.get("height", "?")
|
|
2060
|
-
lines.append(f"{idx}. 图片 ({width}×{height}): {file_path}")
|
|
2061
|
-
elif file_type == "document":
|
|
2062
|
-
original_name = media.get("original_name", "未命名文档")
|
|
2063
|
-
size_mb = media.get("size", 0) / 1024 / 1024
|
|
2064
|
-
lines.append(f"{idx}. 文档 [{original_name}] ({size_mb:.1f}MB): {file_path}")
|
|
2065
|
-
|
|
2066
|
-
# 为不同模型添加特定指令
|
|
2067
|
-
if _is_claudecode_model():
|
|
2068
|
-
lines.append("\n请使用 Read 工具查看上述文件以理解其内容。")
|
|
2069
|
-
elif MODEL_CANONICAL_NAME == "codex":
|
|
2070
|
-
lines.append("\n请分析上述文件并结合任务要求进行处理。")
|
|
2071
|
-
elif "gemini" in MODEL_CANONICAL_NAME:
|
|
2072
|
-
lines.append("\n请查看并分析上述文件。")
|
|
2073
|
-
|
|
2074
|
-
return "\n".join(lines)
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
2001
|
try:
|
|
2078
2002
|
SHANGHAI_TZ = ZoneInfo("Asia/Shanghai")
|
|
2079
2003
|
except ZoneInfoNotFoundError:
|
|
@@ -3051,61 +2975,6 @@ def _collect_message_payload(message: Message) -> str:
|
|
|
3051
2975
|
return "\n".join(parts).strip()
|
|
3052
2976
|
|
|
3053
2977
|
|
|
3054
|
-
async def _collect_message_payload_with_media(
|
|
3055
|
-
message: Message,
|
|
3056
|
-
task_id: Optional[str] = None
|
|
3057
|
-
) -> Tuple[str, List[Dict[str, Any]], Optional[str]]:
|
|
3058
|
-
"""
|
|
3059
|
-
收集消息内容和媒体文件(增强版)
|
|
3060
|
-
返回: (文本内容, 媒体文件列表, 用户提示消息)
|
|
3061
|
-
"""
|
|
3062
|
-
parts = []
|
|
3063
|
-
media_files = []
|
|
3064
|
-
user_feedback = None
|
|
3065
|
-
|
|
3066
|
-
# 处理文本
|
|
3067
|
-
text = _normalize_choice_token(message.text or message.caption)
|
|
3068
|
-
if text:
|
|
3069
|
-
parts.append(text)
|
|
3070
|
-
|
|
3071
|
-
# 处理媒体文件
|
|
3072
|
-
if media_handler and (message.photo or message.document):
|
|
3073
|
-
media_info, feedback_msg = await media_handler.process_message_media(
|
|
3074
|
-
message, task_id
|
|
3075
|
-
)
|
|
3076
|
-
|
|
3077
|
-
if media_info["type"] not in ["none", "error"]:
|
|
3078
|
-
media_files.append(media_info)
|
|
3079
|
-
# 添加文件引用到文本
|
|
3080
|
-
if media_info["type"] == "image":
|
|
3081
|
-
parts.append(f"[图片: {media_info['file_path']}]")
|
|
3082
|
-
elif media_info["type"] == "document":
|
|
3083
|
-
parts.append(f"[文档: {media_info['file_path']}]")
|
|
3084
|
-
elif media_info["type"] == "error":
|
|
3085
|
-
# 添加错误信息到文本
|
|
3086
|
-
parts.append(f"[媒体处理失败: {media_info.get('error', '未知错误')}]")
|
|
3087
|
-
|
|
3088
|
-
# 设置用户反馈
|
|
3089
|
-
user_feedback = feedback_msg
|
|
3090
|
-
else:
|
|
3091
|
-
# 没有媒体处理器时,使用原有逻辑
|
|
3092
|
-
if message.photo:
|
|
3093
|
-
file_id = message.photo[-1].file_id
|
|
3094
|
-
parts.append(f"[图片:{file_id}]")
|
|
3095
|
-
if message.document:
|
|
3096
|
-
doc = message.document
|
|
3097
|
-
name = doc.file_name or doc.file_id
|
|
3098
|
-
parts.append(f"[文件:{name}]")
|
|
3099
|
-
|
|
3100
|
-
# 处理其他媒体类型(保持原有逻辑)
|
|
3101
|
-
if message.voice:
|
|
3102
|
-
parts.append(f"[语音: {message.voice.file_id}]")
|
|
3103
|
-
if message.video:
|
|
3104
|
-
parts.append(f"[视频: {message.video.file_id}]")
|
|
3105
|
-
|
|
3106
|
-
return "\n".join(parts).strip(), media_files, user_feedback
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
2978
|
def _summarize_note_text(value: str) -> str:
|
|
3110
2979
|
"""压缩备注内容,维持主要信息并控制长度。"""
|
|
3111
2980
|
|
|
@@ -3562,9 +3431,6 @@ def tmux_capture_since(log_path: Path | str, start_pos: int, idle: float = 2.0,
|
|
|
3562
3431
|
return "".join(buf)
|
|
3563
3432
|
|
|
3564
3433
|
|
|
3565
|
-
# 全局媒体处理器
|
|
3566
|
-
media_handler: Optional[MediaHandler] = None
|
|
3567
|
-
|
|
3568
3434
|
SESSION_OFFSETS: Dict[str, int] = {}
|
|
3569
3435
|
CHAT_SESSION_MAP: Dict[int, str] = {}
|
|
3570
3436
|
CHAT_WATCHERS: Dict[int, asyncio.Task] = {}
|
|
@@ -5311,7 +5177,6 @@ async def on_help_command(message: Message) -> None:
|
|
|
5311
5177
|
"*指令总览*\n"
|
|
5312
5178
|
"- /help — 查看全部命令\n"
|
|
5313
5179
|
"- /tasks — 任务管理命令清单\n"
|
|
5314
|
-
"- /media — 查看媒体文件统计和管理\n"
|
|
5315
5180
|
"- /task_new — 创建任务(交互式或附带参数)\n"
|
|
5316
5181
|
"- /task_list — 查看任务列表,支持 status/limit/offset\n"
|
|
5317
5182
|
"- /task_show — 查看某个任务详情\n"
|
|
@@ -5340,158 +5205,6 @@ async def on_tasks_help(message: Message) -> None:
|
|
|
5340
5205
|
await _answer_with_markdown(message, text)
|
|
5341
5206
|
|
|
5342
5207
|
|
|
5343
|
-
@router.message(Command("media"))
|
|
5344
|
-
async def on_media_command(message: Message) -> None:
|
|
5345
|
-
"""处理 /media 命令,显示媒体文件统计和管理选项"""
|
|
5346
|
-
global media_handler
|
|
5347
|
-
|
|
5348
|
-
if not media_handler:
|
|
5349
|
-
await message.reply("❌ 媒体处理功能未初始化")
|
|
5350
|
-
return
|
|
5351
|
-
|
|
5352
|
-
try:
|
|
5353
|
-
# 获取媒体文件统计
|
|
5354
|
-
stats = await media_handler.get_stats()
|
|
5355
|
-
|
|
5356
|
-
# 构建统计信息文本
|
|
5357
|
-
lines = [
|
|
5358
|
-
"*📊 媒体文件统计*",
|
|
5359
|
-
"",
|
|
5360
|
-
f"📁 存储位置: `{stats['storage_path']}`",
|
|
5361
|
-
f"📷 图片文件: {stats['image_count']} 个",
|
|
5362
|
-
f"📄 文档文件: {stats['document_count']} 个",
|
|
5363
|
-
f"💾 总占用空间: {stats['total_size_mb']:.2f} MB",
|
|
5364
|
-
"",
|
|
5365
|
-
f"⏰ 普通文件保留: {stats['normal_retention_days']} 天",
|
|
5366
|
-
f"🎯 任务文件保留: {stats['task_retention_days']} 天",
|
|
5367
|
-
"",
|
|
5368
|
-
f"🗑️ 待清理文件: {stats['expired_count']} 个",
|
|
5369
|
-
]
|
|
5370
|
-
|
|
5371
|
-
if stats['expired_count'] > 0:
|
|
5372
|
-
lines.append(f" ({stats['expired_size_mb']:.2f} MB 可释放)")
|
|
5373
|
-
|
|
5374
|
-
# 最近的文件
|
|
5375
|
-
if stats['recent_files']:
|
|
5376
|
-
lines.extend([
|
|
5377
|
-
"",
|
|
5378
|
-
"*📝 最近下载的文件:*"
|
|
5379
|
-
])
|
|
5380
|
-
for file_info in stats['recent_files'][:5]:
|
|
5381
|
-
file_type = "📷" if file_info['type'] == 'image' else "📄"
|
|
5382
|
-
lines.append(f"{file_type} {file_info['name']} ({file_info['size_mb']:.2f} MB)")
|
|
5383
|
-
|
|
5384
|
-
text = "\n".join(lines)
|
|
5385
|
-
|
|
5386
|
-
# 创建管理按钮
|
|
5387
|
-
keyboard = InlineKeyboardMarkup(
|
|
5388
|
-
inline_keyboard=[
|
|
5389
|
-
[
|
|
5390
|
-
InlineKeyboardButton(text="🗑️ 立即清理过期文件", callback_data="media_cleanup"),
|
|
5391
|
-
InlineKeyboardButton(text="🔄 刷新统计", callback_data="media_refresh")
|
|
5392
|
-
]
|
|
5393
|
-
]
|
|
5394
|
-
)
|
|
5395
|
-
|
|
5396
|
-
await _answer_with_markdown(message, text, reply_markup=keyboard)
|
|
5397
|
-
|
|
5398
|
-
except Exception as e:
|
|
5399
|
-
worker_log.error(f"获取媒体统计失败: {e}", exc_info=True)
|
|
5400
|
-
await message.reply(f"❌ 获取媒体统计失败: {e}")
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
@router.callback_query(F.data == "media_cleanup")
|
|
5404
|
-
async def on_media_cleanup_callback(callback: CallbackQuery) -> None:
|
|
5405
|
-
"""处理清理过期文件的回调"""
|
|
5406
|
-
global media_handler
|
|
5407
|
-
|
|
5408
|
-
if not media_handler:
|
|
5409
|
-
await callback.answer("❌ 媒体处理功能未初始化", show_alert=True)
|
|
5410
|
-
return
|
|
5411
|
-
|
|
5412
|
-
try:
|
|
5413
|
-
# 执行清理
|
|
5414
|
-
cleaned_count = await media_handler.cleanup_old_files()
|
|
5415
|
-
|
|
5416
|
-
if cleaned_count > 0:
|
|
5417
|
-
await callback.answer(f"✅ 已清理 {cleaned_count} 个过期文件", show_alert=True)
|
|
5418
|
-
else:
|
|
5419
|
-
await callback.answer("📭 没有需要清理的文件", show_alert=True)
|
|
5420
|
-
|
|
5421
|
-
# 更新统计信息
|
|
5422
|
-
await on_media_refresh_callback(callback)
|
|
5423
|
-
|
|
5424
|
-
except Exception as e:
|
|
5425
|
-
worker_log.error(f"清理媒体文件失败: {e}", exc_info=True)
|
|
5426
|
-
await callback.answer(f"❌ 清理失败: {e}", show_alert=True)
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
@router.callback_query(F.data == "media_refresh")
|
|
5430
|
-
async def on_media_refresh_callback(callback: CallbackQuery) -> None:
|
|
5431
|
-
"""处理刷新统计的回调"""
|
|
5432
|
-
global media_handler
|
|
5433
|
-
|
|
5434
|
-
if not media_handler:
|
|
5435
|
-
await callback.answer("❌ 媒体处理功能未初始化", show_alert=True)
|
|
5436
|
-
return
|
|
5437
|
-
|
|
5438
|
-
try:
|
|
5439
|
-
# 获取最新统计
|
|
5440
|
-
stats = await media_handler.get_stats()
|
|
5441
|
-
|
|
5442
|
-
# 构建更新的文本
|
|
5443
|
-
lines = [
|
|
5444
|
-
"*📊 媒体文件统计*",
|
|
5445
|
-
"",
|
|
5446
|
-
f"📁 存储位置: `{stats['storage_path']}`",
|
|
5447
|
-
f"📷 图片文件: {stats['image_count']} 个",
|
|
5448
|
-
f"📄 文档文件: {stats['document_count']} 个",
|
|
5449
|
-
f"💾 总占用空间: {stats['total_size_mb']:.2f} MB",
|
|
5450
|
-
"",
|
|
5451
|
-
f"⏰ 普通文件保留: {stats['normal_retention_days']} 天",
|
|
5452
|
-
f"🎯 任务文件保留: {stats['task_retention_days']} 天",
|
|
5453
|
-
"",
|
|
5454
|
-
f"🗑️ 待清理文件: {stats['expired_count']} 个",
|
|
5455
|
-
]
|
|
5456
|
-
|
|
5457
|
-
if stats['expired_count'] > 0:
|
|
5458
|
-
lines.append(f" ({stats['expired_size_mb']:.2f} MB 可释放)")
|
|
5459
|
-
|
|
5460
|
-
# 最近的文件
|
|
5461
|
-
if stats['recent_files']:
|
|
5462
|
-
lines.extend([
|
|
5463
|
-
"",
|
|
5464
|
-
"*📝 最近下载的文件:*"
|
|
5465
|
-
])
|
|
5466
|
-
for file_info in stats['recent_files'][:5]:
|
|
5467
|
-
file_type = "📷" if file_info['type'] == 'image' else "📄"
|
|
5468
|
-
lines.append(f"{file_type} {file_info['name']} ({file_info['size_mb']:.2f} MB)")
|
|
5469
|
-
|
|
5470
|
-
text = "\n".join(lines)
|
|
5471
|
-
|
|
5472
|
-
# 保持按钮
|
|
5473
|
-
keyboard = InlineKeyboardMarkup(
|
|
5474
|
-
inline_keyboard=[
|
|
5475
|
-
[
|
|
5476
|
-
InlineKeyboardButton(text="🗑️ 立即清理过期文件", callback_data="media_cleanup"),
|
|
5477
|
-
InlineKeyboardButton(text="🔄 刷新统计", callback_data="media_refresh")
|
|
5478
|
-
]
|
|
5479
|
-
]
|
|
5480
|
-
)
|
|
5481
|
-
|
|
5482
|
-
await callback.message.edit_text(
|
|
5483
|
-
text,
|
|
5484
|
-
parse_mode="MarkdownV2" if _IS_MARKDOWN_V2 else "Markdown",
|
|
5485
|
-
reply_markup=keyboard
|
|
5486
|
-
)
|
|
5487
|
-
|
|
5488
|
-
await callback.answer("✅ 统计已更新")
|
|
5489
|
-
|
|
5490
|
-
except Exception as e:
|
|
5491
|
-
worker_log.error(f"刷新媒体统计失败: {e}", exc_info=True)
|
|
5492
|
-
await callback.answer(f"❌ 刷新失败: {e}", show_alert=True)
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
5208
|
def _normalize_status(value: Optional[str]) -> Optional[str]:
|
|
5496
5209
|
if not value:
|
|
5497
5210
|
return None
|
|
@@ -7172,40 +6885,21 @@ async def on_task_bug_report(callback: CallbackQuery, state: FSMContext) -> None
|
|
|
7172
6885
|
|
|
7173
6886
|
@router.message(TaskBugReportStates.waiting_description)
|
|
7174
6887
|
async def on_task_bug_description(message: Message, state: FSMContext) -> None:
|
|
7175
|
-
"""
|
|
6888
|
+
"""处理缺陷描述输入。"""
|
|
7176
6889
|
|
|
7177
6890
|
if _is_cancel_message(message.text):
|
|
7178
6891
|
await state.clear()
|
|
7179
6892
|
await message.answer("已取消缺陷上报。", reply_markup=_build_worker_main_keyboard())
|
|
7180
6893
|
return
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
data = await state.get_data()
|
|
7184
|
-
task_id = data.get("task_id")
|
|
7185
|
-
|
|
7186
|
-
# 使用增强版收集函数(如果有媒体处理器)
|
|
7187
|
-
if media_handler:
|
|
7188
|
-
content, media_files, feedback = await _collect_message_payload_with_media(
|
|
7189
|
-
message, task_id
|
|
7190
|
-
)
|
|
7191
|
-
# 发送用户反馈
|
|
7192
|
-
if feedback:
|
|
7193
|
-
await message.answer(feedback)
|
|
7194
|
-
else:
|
|
7195
|
-
# 使用原有函数
|
|
7196
|
-
content = _collect_message_payload(message)
|
|
7197
|
-
media_files = []
|
|
7198
|
-
|
|
7199
|
-
if not content and not media_files:
|
|
6894
|
+
content = _collect_message_payload(message)
|
|
6895
|
+
if not content:
|
|
7200
6896
|
await message.answer(
|
|
7201
6897
|
"缺陷描述不能为空,请重新输入:",
|
|
7202
6898
|
reply_markup=_build_description_keyboard(),
|
|
7203
6899
|
)
|
|
7204
6900
|
return
|
|
7205
|
-
|
|
7206
6901
|
await state.update_data(
|
|
7207
6902
|
description=content,
|
|
7208
|
-
media_files=media_files,
|
|
7209
6903
|
reporter=_actor_from_message(message),
|
|
7210
6904
|
)
|
|
7211
6905
|
await state.set_state(TaskBugReportStates.waiting_reproduction)
|
|
@@ -7214,36 +6908,18 @@ async def on_task_bug_description(message: Message, state: FSMContext) -> None:
|
|
|
7214
6908
|
|
|
7215
6909
|
@router.message(TaskBugReportStates.waiting_reproduction)
|
|
7216
6910
|
async def on_task_bug_reproduction(message: Message, state: FSMContext) -> None:
|
|
7217
|
-
"""
|
|
6911
|
+
"""处理复现步骤输入。"""
|
|
7218
6912
|
|
|
7219
6913
|
if _is_cancel_message(message.text):
|
|
7220
6914
|
await state.clear()
|
|
7221
6915
|
await message.answer("已取消缺陷上报。", reply_markup=_build_worker_main_keyboard())
|
|
7222
6916
|
return
|
|
7223
|
-
|
|
7224
6917
|
options = [SKIP_TEXT, "取消"]
|
|
7225
6918
|
resolved = _resolve_reply_choice(message.text or "", options=options)
|
|
7226
6919
|
reproduction = ""
|
|
7227
|
-
reproduction_media = []
|
|
7228
|
-
|
|
7229
6920
|
if resolved not in {SKIP_TEXT, "取消"}:
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
task_id = data.get("task_id")
|
|
7233
|
-
|
|
7234
|
-
if media_handler:
|
|
7235
|
-
reproduction, reproduction_media, feedback = await _collect_message_payload_with_media(
|
|
7236
|
-
message, task_id
|
|
7237
|
-
)
|
|
7238
|
-
if feedback:
|
|
7239
|
-
await message.answer(feedback)
|
|
7240
|
-
else:
|
|
7241
|
-
reproduction = _collect_message_payload(message)
|
|
7242
|
-
|
|
7243
|
-
await state.update_data(
|
|
7244
|
-
reproduction=reproduction,
|
|
7245
|
-
reproduction_media=reproduction_media
|
|
7246
|
-
)
|
|
6921
|
+
reproduction = _collect_message_payload(message)
|
|
6922
|
+
await state.update_data(reproduction=reproduction)
|
|
7247
6923
|
await state.set_state(TaskBugReportStates.waiting_logs)
|
|
7248
6924
|
await message.answer(_build_bug_log_prompt(), reply_markup=_build_description_keyboard())
|
|
7249
6925
|
|
|
@@ -7321,21 +6997,11 @@ async def on_task_bug_confirm(message: Message, state: FSMContext) -> None:
|
|
|
7321
6997
|
reproduction = data.get("reproduction", "")
|
|
7322
6998
|
logs = data.get("logs", "")
|
|
7323
6999
|
reporter = data.get("reporter") or _actor_from_message(message)
|
|
7324
|
-
|
|
7325
|
-
# 收集所有媒体文件
|
|
7326
|
-
all_media_files = []
|
|
7327
|
-
if "media_files" in data:
|
|
7328
|
-
all_media_files.extend(data["media_files"])
|
|
7329
|
-
if "reproduction_media" in data:
|
|
7330
|
-
all_media_files.extend(data["reproduction_media"])
|
|
7331
|
-
|
|
7332
7000
|
payload = {
|
|
7333
7001
|
"action": "bug_report",
|
|
7334
7002
|
"description_length": len(description),
|
|
7335
7003
|
"has_reproduction": bool(reproduction.strip()),
|
|
7336
7004
|
"has_logs": bool(logs.strip()),
|
|
7337
|
-
"has_media": len(all_media_files) > 0,
|
|
7338
|
-
"media_count": len(all_media_files),
|
|
7339
7005
|
"description": description,
|
|
7340
7006
|
"reproduction": reproduction,
|
|
7341
7007
|
"logs": logs,
|
|
@@ -7349,12 +7015,7 @@ async def on_task_bug_confirm(message: Message, state: FSMContext) -> None:
|
|
|
7349
7015
|
payload=payload,
|
|
7350
7016
|
)
|
|
7351
7017
|
await state.clear()
|
|
7352
|
-
await _auto_push_after_bug_report(
|
|
7353
|
-
task,
|
|
7354
|
-
message=message,
|
|
7355
|
-
actor=reporter,
|
|
7356
|
-
media_files=all_media_files
|
|
7357
|
-
)
|
|
7018
|
+
await _auto_push_after_bug_report(task, message=message, actor=reporter)
|
|
7358
7019
|
|
|
7359
7020
|
|
|
7360
7021
|
@router.callback_query(F.data.startswith("task:add_note:"))
|
|
@@ -7747,53 +7408,21 @@ async def on_start(m: Message):
|
|
|
7747
7408
|
if ENV_ISSUES:
|
|
7748
7409
|
await m.answer(_format_env_issue_message())
|
|
7749
7410
|
|
|
7750
|
-
@router.message(F.text
|
|
7411
|
+
@router.message(F.text)
|
|
7751
7412
|
async def on_text(m: Message):
|
|
7752
|
-
"""
|
|
7753
|
-
处理用户消息:支持纯文本、带图片和文档的消息
|
|
7754
|
-
- 纯文本消息:使用 m.text
|
|
7755
|
-
- 带媒体消息:使用 m.caption,并下载媒体文件
|
|
7756
|
-
"""
|
|
7757
7413
|
# 首次收到消息时自动记录 chat_id 到 state 文件
|
|
7758
7414
|
_auto_record_chat_id(m.chat.id)
|
|
7759
7415
|
|
|
7760
|
-
|
|
7761
|
-
prompt = (m.caption or m.text or "").strip()
|
|
7762
|
-
|
|
7763
|
-
# 如果有媒体文件,使用增强收集函数
|
|
7764
|
-
has_media = m.photo or m.document
|
|
7765
|
-
if media_handler and has_media:
|
|
7766
|
-
try:
|
|
7767
|
-
content, media_files, feedback = await _collect_message_payload_with_media(m, None)
|
|
7768
|
-
# 发送用户反馈(下载成功/失败提示)
|
|
7769
|
-
if feedback:
|
|
7770
|
-
await m.answer(feedback)
|
|
7771
|
-
# 使用包含媒体路径引用的完整内容
|
|
7772
|
-
prompt = content
|
|
7773
|
-
except Exception as e:
|
|
7774
|
-
worker_log.error(
|
|
7775
|
-
"处理媒体文件失败: %s",
|
|
7776
|
-
e,
|
|
7777
|
-
exc_info=True,
|
|
7778
|
-
extra={**_session_extra(), "chat": m.chat.id}
|
|
7779
|
-
)
|
|
7780
|
-
# 降级处理:继续使用文本部分
|
|
7781
|
-
await m.answer(f"⚠️ 媒体文件处理失败,仅使用文本内容:{str(e)}")
|
|
7782
|
-
|
|
7416
|
+
prompt = (m.text or "").strip()
|
|
7783
7417
|
if not prompt:
|
|
7784
7418
|
return await m.answer("请输入非空提示词")
|
|
7785
|
-
|
|
7786
|
-
# 快捷查询任务详情(如输入 TASK_0001)
|
|
7787
7419
|
task_id_candidate = _normalize_task_id(prompt)
|
|
7788
7420
|
if task_id_candidate:
|
|
7789
7421
|
await _reply_task_detail_message(m, task_id_candidate)
|
|
7790
7422
|
return
|
|
7791
|
-
|
|
7792
|
-
# 忽略以 / 开头的未识别命令
|
|
7793
7423
|
if prompt.startswith("/"):
|
|
7794
7424
|
return
|
|
7795
7425
|
|
|
7796
|
-
# 环境异常检查
|
|
7797
7426
|
if ENV_ISSUES:
|
|
7798
7427
|
message = _format_env_issue_message()
|
|
7799
7428
|
worker_log.warning(
|
|
@@ -7805,7 +7434,7 @@ async def on_text(m: Message):
|
|
|
7805
7434
|
return
|
|
7806
7435
|
|
|
7807
7436
|
bot = current_bot()
|
|
7808
|
-
await bot.send_chat_action(m.chat.id, "typing") #
|
|
7437
|
+
await bot.send_chat_action(m.chat.id, "typing") # “正在输入”提示
|
|
7809
7438
|
|
|
7810
7439
|
if MODE == "A":
|
|
7811
7440
|
if not AGENT_CMD:
|
|
@@ -7888,28 +7517,8 @@ async def _ensure_worker_menu_button(bot: Bot) -> None:
|
|
|
7888
7517
|
extra={**_session_extra(), "text": WORKER_MENU_BUTTON_TEXT},
|
|
7889
7518
|
)
|
|
7890
7519
|
|
|
7891
|
-
async def _media_cleanup_worker():
|
|
7892
|
-
"""媒体文件定期清理任务"""
|
|
7893
|
-
if not media_handler or not MediaConfig:
|
|
7894
|
-
return
|
|
7895
|
-
|
|
7896
|
-
while True:
|
|
7897
|
-
try:
|
|
7898
|
-
await asyncio.sleep(MediaConfig.AUTO_CLEANUP_INTERVAL_HOURS * 3600)
|
|
7899
|
-
|
|
7900
|
-
if media_handler:
|
|
7901
|
-
cleaned = await media_handler.cleanup_old_files()
|
|
7902
|
-
worker_log.info(
|
|
7903
|
-
"定期清理完成,删除了 %d 个过期文件",
|
|
7904
|
-
cleaned,
|
|
7905
|
-
extra=_session_extra()
|
|
7906
|
-
)
|
|
7907
|
-
|
|
7908
|
-
except Exception as e:
|
|
7909
|
-
worker_log.error("媒体清理任务失败: %s", e, extra=_session_extra())
|
|
7910
|
-
|
|
7911
7520
|
async def main():
|
|
7912
|
-
global _bot, CHAT_LONG_POLL_LOCK
|
|
7521
|
+
global _bot, CHAT_LONG_POLL_LOCK
|
|
7913
7522
|
# 初始化长轮询锁
|
|
7914
7523
|
CHAT_LONG_POLL_LOCK = asyncio.Lock()
|
|
7915
7524
|
_bot = build_bot()
|
|
@@ -7927,16 +7536,6 @@ async def main():
|
|
|
7927
7536
|
if _bot:
|
|
7928
7537
|
await _bot.session.close()
|
|
7929
7538
|
raise SystemExit(1)
|
|
7930
|
-
|
|
7931
|
-
# 初始化媒体处理器
|
|
7932
|
-
if HAS_MEDIA_HANDLER and _bot:
|
|
7933
|
-
try:
|
|
7934
|
-
media_handler = MediaHandler(_bot)
|
|
7935
|
-
# 启动定期清理任务
|
|
7936
|
-
asyncio.create_task(_media_cleanup_worker())
|
|
7937
|
-
worker_log.info("媒体处理器已初始化", extra=_session_extra())
|
|
7938
|
-
except Exception as exc:
|
|
7939
|
-
worker_log.error("媒体处理器初始化失败:%s", exc, extra=_session_extra())
|
|
7940
7539
|
await _ensure_bot_commands(_bot)
|
|
7941
7540
|
await _ensure_worker_menu_button(_bot)
|
|
7942
7541
|
await _broadcast_worker_keyboard(_bot)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
bot.py,sha256=
|
|
1
|
+
bot.py,sha256=EEU9Z-X1QcsIN70nKNDA19zYGoJLt7BKWyQpDNTPtEU,274675
|
|
2
2
|
logging_setup.py,sha256=gvxHi8mUwK3IhXJrsGNTDo-DR6ngkyav1X-tvlBF_IE,4613
|
|
3
3
|
master.py,sha256=Jwxf6I94jOADzb9Xio1wb-tWy5wgQ9PlmdpKW4mhQMg,117114
|
|
4
4
|
project_repository.py,sha256=UcthtSGOJK0cTE5bQCneo3xkomRG-kyc1N1QVqxeHIs,17577
|
|
@@ -426,14 +426,14 @@ tasks/constants.py,sha256=tS1kZxBIUm3JJUMHm25XI-KHNUZl5NhbbuzjzL_rF-c,299
|
|
|
426
426
|
tasks/fsm.py,sha256=rKXXLEieQQU4r2z_CZUvn1_70FXiZXBBugF40gpe_tQ,1476
|
|
427
427
|
tasks/models.py,sha256=N_qqRBo9xMSV0vbn4k6bLBXT8C_dp_oTFUxvdx16ZQM,2459
|
|
428
428
|
tasks/service.py,sha256=w_S_aWiVqRXzXEpimLDsuCCCX2lB5uDkff9aKThBw9c,41916
|
|
429
|
-
vibego_cli/__init__.py,sha256=
|
|
429
|
+
vibego_cli/__init__.py,sha256=X2jkHBM3C13k76pNE_JPkacyuxp6z5r0XZwb58Ik-YY,311
|
|
430
430
|
vibego_cli/__main__.py,sha256=qqTrYmRRLe4361fMzbI3-CqpZ7AhTofIHmfp4ykrrBY,158
|
|
431
431
|
vibego_cli/config.py,sha256=VxkPJMq01tA3h3cOkH-z_tiP7pMgfSGGicRvUnCWkhI,3054
|
|
432
432
|
vibego_cli/deps.py,sha256=1nRXI7Dd-S1hYE8DligzK5fIluQWETRUj4_OKL0DikQ,1419
|
|
433
433
|
vibego_cli/main.py,sha256=X__NXwZnIDIFbdKSTbNyZgZHKcPlN0DQz9sqTI1aQ9E,12158
|
|
434
434
|
vibego_cli/data/worker_requirements.txt,sha256=QSt30DSSSHtfucTFPpc7twk9kLS5rVLNTcvDiagxrZg,62
|
|
435
|
-
vibego-0.2.
|
|
436
|
-
vibego-0.2.
|
|
437
|
-
vibego-0.2.
|
|
438
|
-
vibego-0.2.
|
|
439
|
-
vibego-0.2.
|
|
435
|
+
vibego-0.2.54.dist-info/METADATA,sha256=9wx4NUWLXvv6D4nSbVqwvmzyY0oKyILEknrZ8aY8egI,10519
|
|
436
|
+
vibego-0.2.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
437
|
+
vibego-0.2.54.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
|
|
438
|
+
vibego-0.2.54.dist-info/top_level.txt,sha256=R56CT3nW5H5v3ce0l3QDN4-C4qxTrNWzRTwrxnkDX4U,69
|
|
439
|
+
vibego-0.2.54.dist-info/RECORD,,
|
vibego_cli/__init__.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|