vibego 0.2.42__py3-none-any.whl → 0.2.43__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.

master.py CHANGED
@@ -85,6 +85,11 @@ def _get_restart_signal_path() -> Path:
85
85
 
86
86
 
87
87
  RESTART_SIGNAL_PATH = _get_restart_signal_path()
88
+ LEGACY_RESTART_SIGNAL_PATHS: Tuple[Path, ...] = tuple(
89
+ path
90
+ for path in (ROOT_DIR / "state/restart_signal.json",)
91
+ if path != RESTART_SIGNAL_PATH
92
+ )
88
93
  RESTART_SIGNAL_TTL = int(os.environ.get("MASTER_RESTART_SIGNAL_TTL", "1800")) # 默认 30 分钟
89
94
  LOCAL_TZ = ZoneInfo(os.environ.get("MASTER_TIMEZONE", "Asia/Shanghai"))
90
95
  JUMP_BUTTON_TEXT_WIDTH = 40
@@ -1699,48 +1704,57 @@ def _write_restart_signal(message: Message, *, override_user: Optional[User] = N
1699
1704
  )
1700
1705
 
1701
1706
 
1702
- def _read_restart_signal() -> Optional[dict]:
1703
- """读取并验证重启 signal,超时会自动清理"""
1704
- if not RESTART_SIGNAL_PATH.exists():
1705
- return None
1706
- try:
1707
- raw = json.loads(RESTART_SIGNAL_PATH.read_text(encoding="utf-8"))
1708
- if not isinstance(raw, dict):
1709
- raise ValueError("signal payload 必须是对象")
1710
- except Exception as exc:
1711
- log.error("读取重启信号失败: %s", exc)
1712
- _safe_remove(RESTART_SIGNAL_PATH)
1713
- return None
1714
-
1715
- timestamp_raw = raw.get("timestamp")
1716
- if timestamp_raw:
1707
+ def _read_restart_signal() -> Tuple[Optional[dict], Optional[Path]]:
1708
+ """读取并验证重启 signal,兼容历史路径并处理异常/超时情况"""
1709
+ candidates: Tuple[Path, ...] = (RESTART_SIGNAL_PATH, *LEGACY_RESTART_SIGNAL_PATHS)
1710
+ for path in candidates:
1711
+ if not path.exists():
1712
+ continue
1717
1713
  try:
1718
- ts = datetime.fromisoformat(timestamp_raw)
1719
- if ts.tzinfo is None:
1720
- ts = ts.replace(tzinfo=LOCAL_TZ)
1721
- ts_utc = ts.astimezone(timezone.utc)
1722
- age_seconds = (datetime.now(timezone.utc) - ts_utc).total_seconds()
1723
- if age_seconds > RESTART_SIGNAL_TTL:
1724
- log.info(
1725
- "重启信号超时,忽略",
1726
- extra={
1727
- "path": str(RESTART_SIGNAL_PATH),
1728
- "age_seconds": age_seconds,
1729
- "ttl": RESTART_SIGNAL_TTL,
1730
- },
1731
- )
1732
- _safe_remove(RESTART_SIGNAL_PATH)
1733
- return None
1714
+ raw = json.loads(path.read_text(encoding="utf-8"))
1715
+ if not isinstance(raw, dict):
1716
+ raise ValueError("signal payload 必须是对象")
1734
1717
  except Exception as exc:
1735
- log.warning("解析重启信号时间戳失败: %s", exc)
1718
+ log.error("读取重启信号失败: %s", exc, extra={"path": str(path)})
1719
+ _safe_remove(path)
1720
+ continue
1736
1721
 
1737
- return raw
1722
+ timestamp_raw = raw.get("timestamp")
1723
+ if timestamp_raw:
1724
+ try:
1725
+ ts = datetime.fromisoformat(timestamp_raw)
1726
+ if ts.tzinfo is None:
1727
+ ts = ts.replace(tzinfo=LOCAL_TZ)
1728
+ ts_utc = ts.astimezone(timezone.utc)
1729
+ age_seconds = (datetime.now(timezone.utc) - ts_utc).total_seconds()
1730
+ if age_seconds > RESTART_SIGNAL_TTL:
1731
+ log.info(
1732
+ "重启信号超时,忽略",
1733
+ extra={
1734
+ "path": str(path),
1735
+ "age_seconds": age_seconds,
1736
+ "ttl": RESTART_SIGNAL_TTL,
1737
+ },
1738
+ )
1739
+ _safe_remove(path)
1740
+ continue
1741
+ except Exception as exc:
1742
+ log.warning("解析重启信号时间戳失败: %s", exc, extra={"path": str(path)})
1743
+
1744
+ if path != RESTART_SIGNAL_PATH:
1745
+ log.info(
1746
+ "从兼容路径读取重启信号",
1747
+ extra={"path": str(path), "primary": str(RESTART_SIGNAL_PATH)},
1748
+ )
1749
+ return raw, path
1750
+
1751
+ return None, None
1738
1752
 
1739
1753
 
1740
1754
  async def _notify_restart_success(bot: Bot) -> None:
1741
1755
  """在新 master 启动时读取 signal 并通知触发者(改进版:支持超时检测和详细诊断)"""
1742
1756
  restart_expected = os.environ.pop("MASTER_RESTART_EXPECTED", None)
1743
- payload = _read_restart_signal()
1757
+ payload, signal_path = _read_restart_signal()
1744
1758
 
1745
1759
  # 定义重启健康检查阈值(2 分钟)
1746
1760
  RESTART_HEALTHY_THRESHOLD = 120 # 秒
@@ -1754,7 +1768,7 @@ async def _notify_restart_success(bot: Bot) -> None:
1754
1768
  )
1755
1769
  if targets:
1756
1770
  # 检查启动日志是否有错误信息
1757
- error_log_dir = ROOT_DIR / "logs"
1771
+ error_log_dir = LOG_ROOT_PATH
1758
1772
  error_log_hint = ""
1759
1773
  try:
1760
1774
  error_logs = sorted(error_log_dir.glob("master_error_*.log"), key=lambda p: p.stat().st_mtime, reverse=True)
@@ -1775,8 +1789,8 @@ async def _notify_restart_success(bot: Bot) -> None:
1775
1789
  "4. start.sh 启动失败后被清理",
1776
1790
  "",
1777
1791
  "建议检查:",
1778
- f"- 启动日志: {ROOT_DIR}/logs/start.log",
1779
- f"- 运行日志: {ROOT_DIR}/vibe.log",
1792
+ f"- 启动日志: {LOG_ROOT_PATH / 'start.log'}",
1793
+ f"- 运行日志: {LOG_ROOT_PATH / 'vibe.log'}",
1780
1794
  f"- 信号文件: {RESTART_SIGNAL_PATH}",
1781
1795
  ]
1782
1796
  if error_log_hint:
@@ -1798,7 +1812,11 @@ async def _notify_restart_success(bot: Bot) -> None:
1798
1812
  chat_id = int(chat_id_raw)
1799
1813
  except (TypeError, ValueError):
1800
1814
  log.error("重启信号 chat_id 非法: %s", chat_id_raw)
1801
- _safe_remove(RESTART_SIGNAL_PATH)
1815
+ targets = (signal_path, RESTART_SIGNAL_PATH, *LEGACY_RESTART_SIGNAL_PATHS)
1816
+ for candidate in targets:
1817
+ if candidate is None:
1818
+ continue
1819
+ _safe_remove(candidate)
1802
1820
  return
1803
1821
 
1804
1822
  username = payload.get("username")
@@ -1843,7 +1861,7 @@ async def _notify_restart_success(bot: Bot) -> None:
1843
1861
  details.append("⚠️ 重启耗时过长,建议检查:")
1844
1862
  details.append(" - 网络连接是否正常")
1845
1863
  details.append(" - 依赖安装是否卡住")
1846
- details.append(f" - 启动日志: {ROOT_DIR}/logs/start.log")
1864
+ details.append(f" - 启动日志: {LOG_ROOT_PATH / 'start.log'}")
1847
1865
  else:
1848
1866
  message_lines.append("master 已重新上线 ✅")
1849
1867
 
@@ -1860,7 +1878,11 @@ async def _notify_restart_success(bot: Bot) -> None:
1860
1878
  # 重启成功后不再附带项目列表,避免高频重启时产生额外噪音
1861
1879
  log.info("重启成功通知已发送", extra={"chat": chat_id, "duration": restart_duration})
1862
1880
  finally:
1863
- _safe_remove(RESTART_SIGNAL_PATH)
1881
+ candidates = (signal_path, RESTART_SIGNAL_PATH, *LEGACY_RESTART_SIGNAL_PATHS)
1882
+ for candidate in candidates:
1883
+ if candidate is None:
1884
+ continue
1885
+ _safe_remove(candidate)
1864
1886
 
1865
1887
 
1866
1888
  async def _ensure_manager() -> MasterManager:
@@ -25,11 +25,15 @@ from urllib.error import URLError, HTTPError
25
25
  from urllib.request import Request, urlopen
26
26
 
27
27
  # 导入 master 中的配置与工具,复用项目解析逻辑
28
+ ROOT_DIR = Path(__file__).resolve().parent.parent
29
+ ROOT_DIR_STR = str(ROOT_DIR)
30
+ if ROOT_DIR_STR not in sys.path:
31
+ # 确保可以从仓库根目录导入 master 模块
32
+ sys.path.insert(0, ROOT_DIR_STR)
33
+
28
34
  import master # type: ignore
29
35
  from project_repository import ProjectRepository
30
-
31
- ROOT_DIR = Path(__file__).resolve().parent.parent
32
- DEFAULT_MASTER_LOG = ROOT_DIR / "vibe.log"
36
+ DEFAULT_MASTER_LOG = master.LOG_ROOT_PATH / "vibe.log"
33
37
  DEFAULT_TIMEOUT_MASTER = 60.0
34
38
  DEFAULT_TIMEOUT_PROBE = 15.0
35
39
  PROBE_TEXT = "hello"
scripts/start.sh CHANGED
@@ -2,16 +2,21 @@
2
2
  set -eo pipefail
3
3
 
4
4
  ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
- LOCK_FILE="$ROOT_DIR/state/master_restart.lock"
6
- LOG_DIR="$ROOT_DIR/logs"
5
+ MASTER_CONFIG_ROOT="${MASTER_CONFIG_ROOT:-$HOME/.config/vibego}"
6
+ STATE_DIR="$MASTER_CONFIG_ROOT/state"
7
+ LOG_DIR="$MASTER_CONFIG_ROOT/logs"
8
+ LOCK_FILE="$STATE_DIR/master_restart.lock"
7
9
  START_LOG="$LOG_DIR/start.log"
8
- CODEX_STAMP_FILE="$ROOT_DIR/state/npm_codex_install.stamp"
10
+ CODEX_STAMP_FILE="$STATE_DIR/npm_codex_install.stamp"
9
11
  CODEX_INSTALL_TTL="${CODEX_INSTALL_TTL:-86400}"
10
12
 
11
13
  # 统一重启信号文件路径:使用配置目录而非代码目录
12
14
  # 这样 pipx 安装的 master 和源码运行的 master 可以共享同一个信号文件
13
- MASTER_CONFIG_ROOT="${MASTER_CONFIG_ROOT:-$HOME/.config/vibego}"
14
- export MASTER_RESTART_SIGNAL_PATH="$MASTER_CONFIG_ROOT/state/restart_signal.json"
15
+ export MASTER_RESTART_SIGNAL_PATH="$STATE_DIR/restart_signal.json"
16
+ export LOG_ROOT="${LOG_ROOT:-$LOG_DIR}"
17
+ if [[ -z "${LOG_FILE:-}" ]]; then
18
+ export LOG_FILE="$LOG_DIR/vibe.log"
19
+ fi
15
20
 
16
21
  log_line() {
17
22
  local ts
@@ -191,7 +196,7 @@ cleanup_old_master() {
191
196
  local max_wait=10 # 最多等待10秒优雅退出
192
197
  local waited=0
193
198
  local old_pids=""
194
- local master_pid_file="${MASTER_CONFIG_ROOT:-$HOME/.config/vibego}/state/master.pid"
199
+ local master_pid_file="$STATE_DIR/master.pid"
195
200
 
196
201
  # 方案1:优先从 PID 文件读取
197
202
  if [[ -f "$master_pid_file" ]]; then
@@ -401,7 +406,7 @@ if ! kill -0 "$MASTER_PID" 2>/dev/null; then
401
406
  exit 1
402
407
  fi
403
408
 
404
- log_info "master 已后台启动,PID=$MASTER_PID,日志写入 vibe.log"
409
+ log_info "master 已后台启动,PID=$MASTER_PID,日志写入 ${LOG_FILE}"
405
410
 
406
411
  # 健康检查:等待 master 上线并验证关键 worker
407
412
  log_info "开始执行健康检查..."
@@ -417,8 +422,8 @@ else
417
422
  log_error "⚠️ master 健康检查失败,耗时 ${HEALTHCHECK_DURATION}s"
418
423
  log_error "建议检查:"
419
424
  log_error " - 进程状态: ps aux | grep 'python.*master.py'"
420
- log_error " - 启动日志: tail -100 $ROOT_DIR/logs/start.log"
421
- log_error " - 运行日志: tail -100 $ROOT_DIR/vibe.log"
425
+ log_error " - 启动日志: tail -100 $LOG_DIR/start.log"
426
+ log_error " - 运行日志: tail -100 $LOG_FILE"
422
427
  log_error " - 进程 PID: $MASTER_PID"
423
428
 
424
429
  # 检查进程是否仍在运行
scripts/stop_all.sh CHANGED
@@ -2,9 +2,13 @@
2
2
  set -euo pipefail
3
3
 
4
4
  ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
- STATE_DIR="$ROOT_DIR/state"
5
+ MASTER_CONFIG_ROOT="${MASTER_CONFIG_ROOT:-$HOME/.config/vibego}"
6
+ STATE_DIR="$MASTER_CONFIG_ROOT/state"
6
7
  LOCK_FILE="$STATE_DIR/master_restart.lock"
7
8
  RESTART_SIGNAL="$STATE_DIR/restart_signal.json"
9
+ LEGACY_STATE_DIR="$ROOT_DIR/state"
10
+ LEGACY_LOCK_FILE="$LEGACY_STATE_DIR/master_restart.lock"
11
+ LEGACY_RESTART_SIGNAL="$LEGACY_STATE_DIR/restart_signal.json"
8
12
  DEFAULT_TMUX_PREFIX="${TMUX_SESSION_PREFIX:-vibe}"
9
13
  STOP_BOT_SCRIPT="$ROOT_DIR/scripts/stop_bot.sh"
10
14
 
@@ -138,7 +142,7 @@ stop_tmux_sessions() {
138
142
 
139
143
  cleanup_state_files() {
140
144
  local removed=0
141
- for file in "$LOCK_FILE" "$RESTART_SIGNAL"; do
145
+ for file in "$LOCK_FILE" "$RESTART_SIGNAL" "$LEGACY_LOCK_FILE" "$LEGACY_RESTART_SIGNAL"; do
142
146
  if [[ -e "$file" ]]; then
143
147
  if (( DRY_RUN )); then
144
148
  log_info "[dry-run] rm -f $file"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibego
3
- Version: 0.2.42
3
+ Version: 0.2.43
4
4
  Summary: vibego CLI:用于初始化与管理 Telegram Master Bot 的工具
5
5
  Author: Hypha
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,17 +1,17 @@
1
1
  bot.py,sha256=TthqY_Rvndzd3pgLH6lvPcsDXQbwkuMfB4W9qt_Li8I,273832
2
2
  logging_setup.py,sha256=gvxHi8mUwK3IhXJrsGNTDo-DR6ngkyav1X-tvlBF_IE,4613
3
- master.py,sha256=ZW4A3Gh0MUKFnfZX-VJ7OCNnBzlEcOWkPKYH92OfyKA,112967
3
+ master.py,sha256=uFRhROoRvd93CTRzS6DdlvxMYok7q1jRWZwe8QrTqIY,113997
4
4
  project_repository.py,sha256=UcthtSGOJK0cTE5bQCneo3xkomRG-kyc1N1QVqxeHIs,17577
5
5
  scripts/__init__.py,sha256=LVrXUkvWKoc6Sb47X5G0gbIxu5aJ2ARW-qJ14vwi5vM,65
6
6
  scripts/bump_version.sh,sha256=a4uB8V8Y5LPsoqTCdzQKsEE8HhwpBmqRaQInG52LDig,4089
7
7
  scripts/log_writer.py,sha256=8euoMlRo7cbtHApbcEoJnwzLABxti-ovJWFLRN1oDQw,3843
8
- scripts/master_healthcheck.py,sha256=-X0VVsZ0AXaOb7izxTO_oyu23g_1jsirNdGIcP8nrSI,8321
8
+ scripts/master_healthcheck.py,sha256=kvE6owdqyLmfQ-UYY_jglg86xFzOc87sINxBe5_qWzk,8489
9
9
  scripts/publish.sh,sha256=ehLfMedcXuGKJ87jpZy3kuiFszG9Cpavp3zXPfR4h-g,3511
10
10
  scripts/requirements.txt,sha256=ukJbFLJyzqnQYMz6j07O-IOrG87IwXg0oikmn1nfJ9M,91
11
11
  scripts/run_bot.sh,sha256=rN4K1nz041XBaUJmnBBKHS2cHmQf11vPNX8wf1hbVR4,4596
12
- scripts/start.sh,sha256=w1Q35NB-9FRZAez5I5veqgYIJ8XnVukGt8TTE_ad248,13608
12
+ scripts/start.sh,sha256=1jmO-UVsLskIMdh_2qn130PZ80bVl3CiFpP6XKaXiJk,13695
13
13
  scripts/start_tmux_codex.sh,sha256=xyLv29p924q-ysxvZYAP3T6VrqLPBPMBWo9QP7cuL50,4438
14
- scripts/stop_all.sh,sha256=FOz07gi2CI9sMHxBb8XkqHtxRYs3jt1RYgGrEi-htVg,4086
14
+ scripts/stop_all.sh,sha256=VbNX4h8g1RcnGmLyutPcSySTHb84eIMbo3Ve9Vh-CDg,4360
15
15
  scripts/stop_bot.sh,sha256=ot6Sm0IYoXuRNslUVEflQmJKu5Agm-5xIUXXudJWyTM,5588
16
16
  scripts/test_deps_check.sh,sha256=AeSTucbNuNdOPSGvqVp0m31TVFDb0DmU8gSKg-Y5z2I,1696
17
17
  scripts/.venv/lib/python3.14/site-packages/pip/__init__.py,sha256=_lgs5Mfp0t7AGtI7sTVwxKWquz_vahWWH9kKO1cJusA,353
@@ -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=dM5R5cK5kft5hzz0-VxwpKzzUMt5ZpQqfPLQaDyAILg,311
429
+ vibego_cli/__init__.py,sha256=kV9sTUnKB8boKxSGFUxB66yqQiYg2LvSz9Yu-vLd8_0,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.42.dist-info/METADATA,sha256=Nw9HJPv7fH0iQmxjRx7wQ_mDoODZ_1hcwmVwJC5TvTI,10519
436
- vibego-0.2.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
437
- vibego-0.2.42.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
438
- vibego-0.2.42.dist-info/top_level.txt,sha256=R56CT3nW5H5v3ce0l3QDN4-C4qxTrNWzRTwrxnkDX4U,69
439
- vibego-0.2.42.dist-info/RECORD,,
435
+ vibego-0.2.43.dist-info/METADATA,sha256=dl3SxrEq4PXFbvL7S9NfXaKYvGyA4XZQr89290NTaV8,10519
436
+ vibego-0.2.43.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
437
+ vibego-0.2.43.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
438
+ vibego-0.2.43.dist-info/top_level.txt,sha256=R56CT3nW5H5v3ce0l3QDN4-C4qxTrNWzRTwrxnkDX4U,69
439
+ vibego-0.2.43.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.42"
10
+ __version__ = "0.2.43"
11
11
 
12
12
  from .main import main # noqa: E402