vibego 0.2.54__py3-none-any.whl → 0.2.55__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 CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
- import asyncio, os, sys, time, uuid, shlex, subprocess, socket, re, json, shutil, hashlib, html
10
+ import asyncio, os, sys, time, uuid, shlex, subprocess, socket, re, json, shutil, hashlib, html, mimetypes
11
11
  from datetime import datetime, UTC
12
12
  from pathlib import Path
13
13
  from typing import Any, Dict, Optional, Sequence, Tuple, List, Callable, Awaitable, Literal
@@ -108,6 +108,19 @@ def _env_int(name: str, default: int) -> int:
108
108
  worker_log.warning("环境变量 %s=%r 解析为整数失败,已使用默认值 %s", name, raw, default)
109
109
  return default
110
110
 
111
+
112
+ def _env_float(name: str, default: float) -> float:
113
+ """读取浮点型环境变量,解析失败时回退默认值。"""
114
+
115
+ raw = os.environ.get(name)
116
+ if raw is None or not raw.strip():
117
+ return default
118
+ try:
119
+ return float(raw.strip())
120
+ except ValueError:
121
+ worker_log.warning("环境变量 %s=%r 解析为浮点数失败,已使用默认值 %s", name, raw, default)
122
+ return default
123
+
111
124
  _PARSE_MODE_CANDIDATES: Dict[str, Optional[ParseMode]] = {
112
125
  "": None,
113
126
  "none": None,
@@ -1290,6 +1303,439 @@ PROJECT_SLUG = (PROJECT_NAME or "default").replace("/", "-") or "default"
1290
1303
  TASK_DB_PATH = DATA_ROOT / f"{PROJECT_SLUG}.db"
1291
1304
  TASK_SERVICE = TaskService(TASK_DB_PATH, PROJECT_SLUG)
1292
1305
 
1306
+ ATTACHMENT_STORAGE_ROOT = (DATA_ROOT / "telegram").expanduser()
1307
+ ATTACHMENT_STORAGE_ROOT.mkdir(parents=True, exist_ok=True)
1308
+ _ATTACHMENT_TOTAL_MB = max(_env_int("TELEGRAM_ATTACHMENT_MAX_TOTAL_MB", 512), 16)
1309
+ ATTACHMENT_TOTAL_LIMIT_BYTES = _ATTACHMENT_TOTAL_MB * 1024 * 1024
1310
+ MEDIA_GROUP_AGGREGATION_DELAY = max(_env_float("TELEGRAM_MEDIA_GROUP_DELAY", 0.8), 0.1)
1311
+
1312
+
1313
+ @dataclass
1314
+ class TelegramSavedAttachment:
1315
+ """记录单个附件的落地信息,便于提示模型读取。"""
1316
+
1317
+ kind: str
1318
+ display_name: str
1319
+ mime_type: str
1320
+ absolute_path: Path
1321
+ relative_path: str
1322
+
1323
+
1324
+ @dataclass
1325
+ class PendingMediaGroupState:
1326
+ """聚合 Telegram 媒体组的临时缓存。"""
1327
+
1328
+ chat_id: int
1329
+ origin_message: Message
1330
+ attachment_dir: Path
1331
+ attachments: list[TelegramSavedAttachment]
1332
+ captions: list[str]
1333
+ finalize_task: Optional[asyncio.Task] = None
1334
+
1335
+
1336
+ MEDIA_GROUP_STATE: dict[str, PendingMediaGroupState] = {}
1337
+ MEDIA_GROUP_LOCK = asyncio.Lock()
1338
+
1339
+ ATTACHMENT_USAGE_HINT = (
1340
+ "请按需读取附件:图片可使用 Codex 的 view_image 功能或 Claude Code 的文件引用能力;"
1341
+ "文本/日志可直接通过 @<路径> 打开;若需其他处理请说明。"
1342
+ )
1343
+
1344
+ _FS_SAFE_PATTERN = re.compile(r"[^A-Za-z0-9._-]")
1345
+
1346
+
1347
+ def _sanitize_fs_component(value: str, fallback: str) -> str:
1348
+ """清理路径片段中的特殊字符,避免越权访问。"""
1349
+
1350
+ stripped = (value or "").strip()
1351
+ cleaned = _FS_SAFE_PATTERN.sub("_", stripped)
1352
+ cleaned = cleaned.strip("._")
1353
+ return cleaned or fallback
1354
+
1355
+
1356
+ def _format_relative_path(path: Path) -> str:
1357
+ """将绝对路径转换为模型更易识别的相对路径。"""
1358
+
1359
+ try:
1360
+ rel = path.relative_to(ROOT_DIR_PATH)
1361
+ rel_str = rel.as_posix()
1362
+ if not rel_str.startswith("."):
1363
+ return f"./{rel_str}"
1364
+ return rel_str
1365
+ except ValueError:
1366
+ return path.resolve().as_posix()
1367
+
1368
+
1369
+ def _directory_size(path: Path) -> int:
1370
+ """计算目录占用的总字节数。"""
1371
+
1372
+ total = 0
1373
+ if not path.exists():
1374
+ return 0
1375
+ for entry in path.rglob("*"):
1376
+ try:
1377
+ if entry.is_file():
1378
+ total += entry.stat().st_size
1379
+ except FileNotFoundError:
1380
+ continue
1381
+ return total
1382
+
1383
+
1384
+ def _cleanup_attachment_storage() -> None:
1385
+ """控制附件目录容量,避免磁盘被占满。"""
1386
+
1387
+ if ATTACHMENT_TOTAL_LIMIT_BYTES <= 0:
1388
+ return
1389
+ total = _directory_size(ATTACHMENT_STORAGE_ROOT)
1390
+ if total <= ATTACHMENT_TOTAL_LIMIT_BYTES:
1391
+ return
1392
+ candidates = sorted(
1393
+ (p for p in ATTACHMENT_STORAGE_ROOT.iterdir() if p.is_dir()),
1394
+ key=lambda item: item.stat().st_mtime,
1395
+ )
1396
+ for folder in candidates:
1397
+ try:
1398
+ shutil.rmtree(folder, ignore_errors=True)
1399
+ except Exception as exc: # noqa: BLE001
1400
+ worker_log.warning(
1401
+ "清理旧附件目录失败:%s",
1402
+ exc,
1403
+ extra=_session_extra(path=folder),
1404
+ )
1405
+ if _directory_size(ATTACHMENT_STORAGE_ROOT) <= ATTACHMENT_TOTAL_LIMIT_BYTES:
1406
+ break
1407
+
1408
+
1409
+ def _guess_extension(mime_type: Optional[str], fallback: str = ".bin") -> str:
1410
+ """根据 MIME 类型推断扩展名。"""
1411
+
1412
+ if mime_type:
1413
+ guessed = mimetypes.guess_extension(mime_type, strict=False)
1414
+ if guessed:
1415
+ return guessed
1416
+ return fallback
1417
+
1418
+
1419
+ def _attachment_dir_for_message(message: Message, media_group_id: Optional[str] = None) -> Path:
1420
+ """为当前消息(或媒体组)生成稳定的附件目录。"""
1421
+
1422
+ chat_part = _sanitize_fs_component(str(message.chat.id), "chat")
1423
+ base = ATTACHMENT_STORAGE_ROOT / chat_part
1424
+ if media_group_id:
1425
+ group_part = _sanitize_fs_component(media_group_id, str(message.message_id))
1426
+ target = base / f"group_{group_part}"
1427
+ else:
1428
+ timestamp = int((message.date or datetime.now(UTC)).timestamp())
1429
+ target = base / f"msg_{timestamp}_{message.message_id}"
1430
+ target.mkdir(parents=True, exist_ok=True)
1431
+ return target
1432
+
1433
+
1434
+ async def _download_telegram_file(
1435
+ message: Message,
1436
+ *,
1437
+ file_id: str,
1438
+ file_name_hint: str,
1439
+ mime_type: Optional[str],
1440
+ target_dir: Path,
1441
+ ) -> Path:
1442
+ """从 Telegram 下载文件并返回本地路径。"""
1443
+
1444
+ bot = message.bot or current_bot()
1445
+ telegram_file = await bot.get_file(file_id)
1446
+ stem = _sanitize_fs_component(Path(file_name_hint).stem, "file")
1447
+ extension = Path(file_name_hint).suffix or _guess_extension(mime_type, ".bin")
1448
+ if not extension.startswith("."):
1449
+ extension = f".{extension}"
1450
+ filename = f"{stem}{extension}"
1451
+ destination = target_dir / filename
1452
+ counter = 1
1453
+ while destination.exists():
1454
+ destination = target_dir / f"{stem}_{counter}{extension}"
1455
+ counter += 1
1456
+ await bot.download_file(telegram_file.file_path, destination=destination)
1457
+ return destination
1458
+
1459
+
1460
+ async def _collect_saved_attachments(message: Message, target_dir: Path) -> list[TelegramSavedAttachment]:
1461
+ """下载消息中的所有附件,并返回保存记录。"""
1462
+
1463
+ saved: list[TelegramSavedAttachment] = []
1464
+
1465
+ if message.photo:
1466
+ photo = message.photo[-1]
1467
+ path = await _download_telegram_file(
1468
+ message,
1469
+ file_id=photo.file_id,
1470
+ file_name_hint=f"photo_{photo.file_unique_id}.jpg",
1471
+ mime_type="image/jpeg",
1472
+ target_dir=target_dir,
1473
+ )
1474
+ saved.append(
1475
+ TelegramSavedAttachment(
1476
+ kind="photo",
1477
+ display_name=path.name,
1478
+ mime_type="image/jpeg",
1479
+ absolute_path=path,
1480
+ relative_path=_format_relative_path(path),
1481
+ )
1482
+ )
1483
+
1484
+ document = message.document
1485
+ if document:
1486
+ file_name = document.file_name or f"document_{document.file_unique_id}"
1487
+ path = await _download_telegram_file(
1488
+ message,
1489
+ file_id=document.file_id,
1490
+ file_name_hint=file_name,
1491
+ mime_type=document.mime_type or "application/octet-stream",
1492
+ target_dir=target_dir,
1493
+ )
1494
+ saved.append(
1495
+ TelegramSavedAttachment(
1496
+ kind="document",
1497
+ display_name=file_name,
1498
+ mime_type=document.mime_type or "application/octet-stream",
1499
+ absolute_path=path,
1500
+ relative_path=_format_relative_path(path),
1501
+ )
1502
+ )
1503
+
1504
+ video = message.video
1505
+ if video:
1506
+ file_name = video.file_name or f"video_{video.file_unique_id}"
1507
+ path = await _download_telegram_file(
1508
+ message,
1509
+ file_id=video.file_id,
1510
+ file_name_hint=file_name,
1511
+ mime_type=video.mime_type or "video/mp4",
1512
+ target_dir=target_dir,
1513
+ )
1514
+ saved.append(
1515
+ TelegramSavedAttachment(
1516
+ kind="video",
1517
+ display_name=file_name,
1518
+ mime_type=video.mime_type or "video/mp4",
1519
+ absolute_path=path,
1520
+ relative_path=_format_relative_path(path),
1521
+ )
1522
+ )
1523
+
1524
+ audio = message.audio
1525
+ if audio:
1526
+ file_name = audio.file_name or f"audio_{audio.file_unique_id}"
1527
+ path = await _download_telegram_file(
1528
+ message,
1529
+ file_id=audio.file_id,
1530
+ file_name_hint=file_name,
1531
+ mime_type=audio.mime_type or "audio/mpeg",
1532
+ target_dir=target_dir,
1533
+ )
1534
+ saved.append(
1535
+ TelegramSavedAttachment(
1536
+ kind="audio",
1537
+ display_name=file_name,
1538
+ mime_type=audio.mime_type or "audio/mpeg",
1539
+ absolute_path=path,
1540
+ relative_path=_format_relative_path(path),
1541
+ )
1542
+ )
1543
+
1544
+ voice = message.voice
1545
+ if voice:
1546
+ file_name = f"voice_{voice.file_unique_id}.ogg"
1547
+ path = await _download_telegram_file(
1548
+ message,
1549
+ file_id=voice.file_id,
1550
+ file_name_hint=file_name,
1551
+ mime_type=voice.mime_type or "audio/ogg",
1552
+ target_dir=target_dir,
1553
+ )
1554
+ saved.append(
1555
+ TelegramSavedAttachment(
1556
+ kind="voice",
1557
+ display_name=file_name,
1558
+ mime_type=voice.mime_type or "audio/ogg",
1559
+ absolute_path=path,
1560
+ relative_path=_format_relative_path(path),
1561
+ )
1562
+ )
1563
+
1564
+ animation = message.animation
1565
+ if animation:
1566
+ file_name = animation.file_name or f"animation_{animation.file_unique_id}"
1567
+ path = await _download_telegram_file(
1568
+ message,
1569
+ file_id=animation.file_id,
1570
+ file_name_hint=file_name,
1571
+ mime_type=animation.mime_type or "video/mp4",
1572
+ target_dir=target_dir,
1573
+ )
1574
+ saved.append(
1575
+ TelegramSavedAttachment(
1576
+ kind="animation",
1577
+ display_name=file_name,
1578
+ mime_type=animation.mime_type or "video/mp4",
1579
+ absolute_path=path,
1580
+ relative_path=_format_relative_path(path),
1581
+ )
1582
+ )
1583
+
1584
+ video_note = message.video_note
1585
+ if video_note:
1586
+ file_name = f"video_note_{video_note.file_unique_id}.mp4"
1587
+ path = await _download_telegram_file(
1588
+ message,
1589
+ file_id=video_note.file_id,
1590
+ file_name_hint=file_name,
1591
+ mime_type=video_note.mime_type or "video/mp4",
1592
+ target_dir=target_dir,
1593
+ )
1594
+ saved.append(
1595
+ TelegramSavedAttachment(
1596
+ kind="video_note",
1597
+ display_name=file_name,
1598
+ mime_type=video_note.mime_type or "video/mp4",
1599
+ absolute_path=path,
1600
+ relative_path=_format_relative_path(path),
1601
+ )
1602
+ )
1603
+
1604
+ if saved:
1605
+ _cleanup_attachment_storage()
1606
+ return saved
1607
+
1608
+
1609
+ def _build_prompt_with_attachments(
1610
+ text_part: Optional[str],
1611
+ attachments: Sequence[TelegramSavedAttachment],
1612
+ ) -> str:
1613
+ """将文字与附件描述拼接成模型可读的提示。"""
1614
+
1615
+ sections: list[str] = []
1616
+ base_text = (text_part or "").strip()
1617
+ if base_text:
1618
+ sections.append(base_text)
1619
+ if attachments:
1620
+ lines = ["附件列表(文件位于项目工作目录,可直接读取):"]
1621
+ for idx, item in enumerate(attachments, 1):
1622
+ lines.append(
1623
+ f"{idx}. {item.display_name}({item.mime_type})→ {item.relative_path}"
1624
+ )
1625
+ lines.append("")
1626
+ lines.append(ATTACHMENT_USAGE_HINT)
1627
+ sections.append("\n".join(lines))
1628
+ if not sections:
1629
+ fallback = [
1630
+ "收到一条仅包含附件的消息,没有额外文字说明。",
1631
+ "请直接阅读列出的附件并给出观察结果或结论。",
1632
+ ]
1633
+ sections.append("\n".join(fallback))
1634
+ return "\n\n".join(sections).strip()
1635
+
1636
+
1637
+ async def _finalize_media_group_after_delay(media_group_id: str) -> None:
1638
+ """在短暂延迟后合并媒体组消息,确保 Telegram 全部照片到齐。"""
1639
+
1640
+ try:
1641
+ await asyncio.sleep(MEDIA_GROUP_AGGREGATION_DELAY)
1642
+ except asyncio.CancelledError:
1643
+ return
1644
+
1645
+ async with MEDIA_GROUP_LOCK:
1646
+ state = MEDIA_GROUP_STATE.pop(media_group_id, None)
1647
+
1648
+ if state is None:
1649
+ return
1650
+
1651
+ text_block = "\n".join(state.captions).strip()
1652
+ prompt = _build_prompt_with_attachments(text_block, state.attachments)
1653
+ try:
1654
+ await _handle_prompt_dispatch(state.origin_message, prompt)
1655
+ except Exception as exc: # noqa: BLE001
1656
+ worker_log.exception(
1657
+ "媒体组消息推送模型失败:%s",
1658
+ exc,
1659
+ extra=_session_extra(media_group=media_group_id),
1660
+ )
1661
+
1662
+
1663
+ async def _enqueue_media_group_message(message: Message, text_part: Optional[str]) -> None:
1664
+ """收集媒体组中的每一条消息,统一延迟推送。"""
1665
+
1666
+ media_group_id = message.media_group_id
1667
+ if not media_group_id:
1668
+ return
1669
+
1670
+ async with MEDIA_GROUP_LOCK:
1671
+ state = MEDIA_GROUP_STATE.get(media_group_id)
1672
+ if state is None:
1673
+ attachment_dir = _attachment_dir_for_message(message, media_group_id=media_group_id)
1674
+ state = PendingMediaGroupState(
1675
+ chat_id=message.chat.id,
1676
+ origin_message=message,
1677
+ attachment_dir=attachment_dir,
1678
+ attachments=[],
1679
+ captions=[],
1680
+ )
1681
+ MEDIA_GROUP_STATE[media_group_id] = state
1682
+ else:
1683
+ attachment_dir = state.attachment_dir
1684
+
1685
+ attachments = await _collect_saved_attachments(message, attachment_dir)
1686
+ caption = (text_part or "").strip()
1687
+
1688
+ async with MEDIA_GROUP_LOCK:
1689
+ state = MEDIA_GROUP_STATE.get(media_group_id)
1690
+ if state is None:
1691
+ # 若期间被清理,重新创建并继续积累,避免丢失后续内容。
1692
+ state = PendingMediaGroupState(
1693
+ chat_id=message.chat.id,
1694
+ origin_message=message,
1695
+ attachment_dir=attachment_dir,
1696
+ attachments=[],
1697
+ captions=[],
1698
+ )
1699
+ MEDIA_GROUP_STATE[media_group_id] = state
1700
+ state.attachments.extend(attachments)
1701
+ if caption:
1702
+ state.captions.append(caption)
1703
+ # 使用首条消息作为引用对象,便于 Telegram 回复。
1704
+ if state.origin_message.message_id > message.message_id:
1705
+ state.origin_message = message
1706
+ if state.finalize_task and not state.finalize_task.done():
1707
+ state.finalize_task.cancel()
1708
+ state.finalize_task = asyncio.create_task(_finalize_media_group_after_delay(media_group_id))
1709
+
1710
+
1711
+ async def _handle_prompt_dispatch(message: Message, prompt: str) -> None:
1712
+ """统一封装向模型推送提示词的流程。"""
1713
+
1714
+ if ENV_ISSUES:
1715
+ message_text = _format_env_issue_message()
1716
+ worker_log.warning(
1717
+ "拒绝处理消息,环境异常: %s",
1718
+ message_text,
1719
+ extra={**_session_extra(), "chat": message.chat.id},
1720
+ )
1721
+ await message.answer(message_text)
1722
+ return
1723
+
1724
+ bot = current_bot()
1725
+ await bot.send_chat_action(message.chat.id, "typing")
1726
+
1727
+ if MODE == "A":
1728
+ if not AGENT_CMD:
1729
+ await message.answer("AGENT_CMD 未配置(.env)")
1730
+ return
1731
+ rc, out = run_subprocess_capture(AGENT_CMD, input_text=prompt)
1732
+ out = out or ""
1733
+ out = out + ("" if rc == 0 else f"\n(exit={rc})")
1734
+ await reply_large_text(message.chat.id, out)
1735
+ return
1736
+
1737
+ await _dispatch_prompt_to_model(message.chat.id, prompt, reply_to=message)
1738
+
1293
1739
  BOT_COMMANDS: list[tuple[str, str]] = [
1294
1740
  ("help", "查看全部命令"),
1295
1741
  ("tasks", "任务命令清单"),
@@ -7390,6 +7836,28 @@ async def on_edit_new_value(message: Message, state: FSMContext) -> None:
7390
7836
  await _answer_with_markdown(message, f"任务已更新:\n{detail_text}", reply_markup=markup)
7391
7837
 
7392
7838
 
7839
+ @router.message(
7840
+ F.photo | F.document | F.video | F.audio | F.voice | F.animation | F.video_note
7841
+ )
7842
+ async def on_media_message(message: Message) -> None:
7843
+ """处理带附件的普通消息,将附件下载并拼接提示词。"""
7844
+
7845
+ _auto_record_chat_id(message.chat.id)
7846
+ text_part = (message.caption or message.text or "").strip()
7847
+
7848
+ if message.media_group_id:
7849
+ await _enqueue_media_group_message(message, text_part)
7850
+ return
7851
+
7852
+ attachment_dir = _attachment_dir_for_message(message)
7853
+ attachments = await _collect_saved_attachments(message, attachment_dir)
7854
+ if not attachments and not text_part:
7855
+ await message.answer("未检测到可处理的附件或文字内容。")
7856
+ return
7857
+ prompt = _build_prompt_with_attachments(text_part, attachments)
7858
+ await _handle_prompt_dispatch(message, prompt)
7859
+
7860
+
7393
7861
  @router.message(CommandStart())
7394
7862
  async def on_start(m: Message):
7395
7863
  # 首次收到消息时自动记录 chat_id 到 state 文件
@@ -7422,30 +7890,7 @@ async def on_text(m: Message):
7422
7890
  return
7423
7891
  if prompt.startswith("/"):
7424
7892
  return
7425
-
7426
- if ENV_ISSUES:
7427
- message = _format_env_issue_message()
7428
- worker_log.warning(
7429
- "拒绝处理消息,环境异常: %s",
7430
- message,
7431
- extra={**_session_extra(), "chat": m.chat.id},
7432
- )
7433
- await m.answer(message)
7434
- return
7435
-
7436
- bot = current_bot()
7437
- await bot.send_chat_action(m.chat.id, "typing") # “正在输入”提示
7438
-
7439
- if MODE == "A":
7440
- if not AGENT_CMD:
7441
- return await m.answer("AGENT_CMD 未配置(.env)")
7442
- rc, out = run_subprocess_capture(AGENT_CMD, input_text=prompt)
7443
- out = out or ""
7444
- out = out + ("" if rc == 0 else f"\n(exit={rc})")
7445
- await reply_large_text(m.chat.id, out)
7446
-
7447
- else:
7448
- await _dispatch_prompt_to_model(m.chat.id, prompt, reply_to=m)
7893
+ await _handle_prompt_dispatch(m, prompt)
7449
7894
 
7450
7895
 
7451
7896
  async def ensure_telegram_connectivity(bot: Bot, timeout: float = 30.0):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibego
3
- Version: 0.2.54
3
+ Version: 0.2.55
4
4
  Summary: vibego CLI:用于初始化与管理 Telegram Master Bot 的工具
5
5
  Author: Hypha
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,4 +1,4 @@
1
- bot.py,sha256=EEU9Z-X1QcsIN70nKNDA19zYGoJLt7BKWyQpDNTPtEU,274675
1
+ bot.py,sha256=hjebHpgW7tR9fNxkdbgNLFNYaz4MNgtsq_Sci2VljPM,289835
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=X2jkHBM3C13k76pNE_JPkacyuxp6z5r0XZwb58Ik-YY,311
429
+ vibego_cli/__init__.py,sha256=asbT5tFazlPcS692PW0b6GBg_fWkYpf-mZn02hiG-p4,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.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,,
435
+ vibego-0.2.55.dist-info/METADATA,sha256=McMxELuZfQ_ByCmOD3gRCEIqec4IHYK1pPNjMpn8xxM,10519
436
+ vibego-0.2.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
437
+ vibego-0.2.55.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
438
+ vibego-0.2.55.dist-info/top_level.txt,sha256=R56CT3nW5H5v3ce0l3QDN4-C4qxTrNWzRTwrxnkDX4U,69
439
+ vibego-0.2.55.dist-info/RECORD,,
vibego_cli/__init__.py CHANGED
@@ -7,6 +7,6 @@ from __future__ import annotations
7
7
 
8
8
  __all__ = ["main", "__version__"]
9
9
 
10
- __version__ = "0.2.54"
10
+ __version__ = "0.2.55"
11
11
 
12
12
  from .main import main # noqa: E402