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

@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env python3
2
- """Master 启动后的健康检查脚本。
2
+ """Master Post-startup health check script.
3
3
 
4
- 流程:
5
- 1. 等待 master 日志出现启动标记。
6
- 2. 调用 MasterManager 启动指定 worker(默认 hyphavibebotbackend)。
7
- 3. 自动发现该 worker chat_id(优先 state 文件,其次读取最新日志)。
8
- 4. 通过 Telegram Bot API 向该 chat 发送探针消息,确认发送成功。
9
- 5. 任何步骤失败则抛出异常,并尝试通知管理员。
4
+ Process:
5
+ 1. Wait for a startup flag to appear in the master log.
6
+ 2. Call MasterManager to start the specified worker (default hyphavibebotbackend).
7
+ 3. Automatically discover the worker's chat_id(Prioritize the state file, then read the latest log).
8
+ 4. Send a probe message to the chat through the Telegram Bot API to confirm that the sending is successful.
9
+ 5. If any step fails, an exception is thrown and an attempt is made to notify the administrator.
10
10
 
11
- 注意:本脚本不会自动重试重启,仅返回非零退出码供外层脚本处理。
11
+ Note: This script will not automatically retry the restart and will only return a non-zero exit code for processing by the outer script.
12
12
  """
13
13
  from __future__ import annotations
14
14
 
@@ -24,11 +24,11 @@ from typing import Optional
24
24
  from urllib.error import URLError, HTTPError
25
25
  from urllib.request import Request, urlopen
26
26
 
27
- # 导入 master 中的配置与工具,复用项目解析逻辑
27
+ # Import the configuration and tools in master and reuse the project parsing logic
28
28
  ROOT_DIR = Path(__file__).resolve().parent.parent
29
29
  ROOT_DIR_STR = str(ROOT_DIR)
30
30
  if ROOT_DIR_STR not in sys.path:
31
- # 确保可以从仓库根目录导入 master 模块
31
+ # Make sure the master module can be imported from the repository root
32
32
  sys.path.insert(0, ROOT_DIR_STR)
33
33
 
34
34
  import master # type: ignore
@@ -41,19 +41,19 @@ REPOSITORY = ProjectRepository(master.CONFIG_DB_PATH, master.CONFIG_PATH)
41
41
 
42
42
 
43
43
  def _load_project(project_id: str) -> master.ProjectConfig:
44
- """根据 slug bot 名获取项目配置,失败时列出可选项。"""
44
+ """Get the project configuration based on the slug or bot name, and list the options on failure."""
45
45
 
46
46
  record = REPOSITORY.get_by_slug(project_id)
47
47
  if record is None:
48
48
  record = REPOSITORY.get_by_bot_name(project_id)
49
49
  if record is None:
50
50
  available = [r.project_slug for r in REPOSITORY.list_projects()]
51
- raise RuntimeError(f"未找到项目 {project_id},可选项目: {available}")
51
+ raise RuntimeError(f"No items found {project_id}, Optional items: {available}")
52
52
  return master.ProjectConfig.from_dict(record.to_dict())
53
53
 
54
54
 
55
55
  def _wait_for_log_flag(path: Path, pattern: str, timeout: float) -> None:
56
- """在超时时间内等待日志出现特定标记。"""
56
+ """Waits for a specific mark in the log within the timeout period."""
57
57
 
58
58
  deadline = time.monotonic() + timeout
59
59
  position = 0
@@ -72,11 +72,11 @@ def _wait_for_log_flag(path: Path, pattern: str, timeout: float) -> None:
72
72
  if pattern in line:
73
73
  return
74
74
  time.sleep(0.5)
75
- raise TimeoutError(f" {timeout:.0f} 秒内未检测到日志标记: {pattern}")
75
+ raise TimeoutError(f"exist {timeout:.0f} No log markers detected in seconds: {pattern}")
76
76
 
77
77
 
78
78
  def _extract_chat_id_from_logs(log_path: Path) -> Optional[int]:
79
- """从日志文件倒序查找最近的 chat_id。"""
79
+ """Find the most recent chat from the log file in reverse order_id."""
80
80
 
81
81
  if not log_path.exists():
82
82
  return None
@@ -85,7 +85,7 @@ def _extract_chat_id_from_logs(log_path: Path) -> Optional[int]:
85
85
  lines = log_path.read_text(encoding="utf-8", errors="ignore").splitlines()
86
86
  except Exception:
87
87
  return None
88
- for line in reversed(lines[-200:]): # 反向查找最近的记录
88
+ for line in reversed(lines[-200:]): # Reverse search for recent records
89
89
  match = pattern.search(line)
90
90
  if match:
91
91
  try:
@@ -96,25 +96,25 @@ def _extract_chat_id_from_logs(log_path: Path) -> Optional[int]:
96
96
 
97
97
 
98
98
  def _ensure_chat_id(cfg: master.ProjectConfig, manager: master.MasterManager) -> int:
99
- """确保任务分配有 chat_id,必要时从日志回填并写回 state"""
99
+ """Make sure the task is assigned chat_id, Backfill from log and write back to state if necessary."""
100
100
 
101
101
  state = manager.state_store.data.get(cfg.project_slug)
102
102
  if state and state.chat_id:
103
103
  return int(state.chat_id)
104
- # 回落到日志查找
104
+ # Fall back to log search
105
105
  log_dir = master.LOG_ROOT_PATH / (cfg.default_model.lower()) / cfg.project_slug
106
106
  chat_id = _extract_chat_id_from_logs(log_dir / "run_bot.log")
107
107
  if chat_id is None:
108
108
  raise RuntimeError(
109
- "无法自动获取 chat_id,请先手动与该 bot 发生一次对话以写入 state/log"
109
+ "Unable to get chat automatically_id, Please manually have a conversation with the bot to write the state/log"
110
110
  )
111
- # 将发现的 chat_id 写回 state,便于下次复用
111
+ # will discover chat_id Write back the state for easy reuse next time
112
112
  manager.state_store.update(cfg.project_slug, chat_id=chat_id)
113
113
  return chat_id
114
114
 
115
115
 
116
116
  def _send_probe(bot_token: str, chat_id: int, text: str, timeout: float) -> None:
117
- """向指定 chat 发送探针消息,验证 Telegram API 可用。"""
117
+ """Send a probe message to the specified chat to verify that the Telegram API is available."""
118
118
 
119
119
  url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
120
120
  payload = json.dumps({"chat_id": chat_id, "text": text, "disable_notification": True}).encode("utf-8")
@@ -122,26 +122,26 @@ def _send_probe(bot_token: str, chat_id: int, text: str, timeout: float) -> None
122
122
  try:
123
123
  with urlopen(request, timeout=timeout) as resp:
124
124
  data = json.loads(resp.read().decode("utf-8"))
125
- except HTTPError as exc: # pragma: no cover - 网络异常时抛出
126
- raise RuntimeError(f"发送探针消息失败,HTTP {exc.code}: {exc.reason}") from exc
127
- except URLError as exc: # pragma: no cover - 网络异常时抛出
128
- raise RuntimeError(f"发送探针消息失败: {exc}") from exc
125
+ except HTTPError as exc: # pragma: no cover - Thrown when network exception occurs
126
+ raise RuntimeError(f"Failed to send probe message, HTTP {exc.code}: {exc.reason}") from exc
127
+ except URLError as exc: # pragma: no cover - Thrown when network exception occurs
128
+ raise RuntimeError(f"Failed to send probe message: {exc}") from exc
129
129
  if not data.get("ok"):
130
- raise RuntimeError(f"发送探针消息失败: {data}")
130
+ raise RuntimeError(f"Failed to send probe message: {data}")
131
131
 
132
132
 
133
133
  def _format_admin_notice(reason: str) -> str:
134
- """生成通知管理员的告警文本。"""
134
+ """Generate alarm text to notify the administrator."""
135
135
 
136
136
  return (
137
- "Master 重启健康检查失败\n"
138
- f"原因:{reason}\n"
139
- "请尽快登录服务器排查(start.log / vibe.log)。"
137
+ "Master Restart health check failed\n"
138
+ f"reason:{reason}\n"
139
+ "Please log in to the server as soon as possible to troubleshoot (start.log / vibe.log)."
140
140
  )
141
141
 
142
142
 
143
143
  def _notify_admins(reason: str) -> None:
144
- """如果 master token 可用,则向管理员列表广播失败原因。"""
144
+ """If the master token is available, the failure reason is broadcast to the administrator list."""
145
145
 
146
146
  master_token = os.environ.get("MASTER_BOT_TOKEN")
147
147
  if not master_token:
@@ -164,7 +164,7 @@ def _notify_admins(reason: str) -> None:
164
164
 
165
165
 
166
166
  def _ensure_worker(cfg: master.ProjectConfig) -> master.MasterManager:
167
- """启动指定项目 worker,并返回临时构造的 MasterManager"""
167
+ """Starts the specified project worker and returns the temporarily constructed MasterManager."""
168
168
 
169
169
  records = REPOSITORY.list_projects()
170
170
  configs = [master.ProjectConfig.from_dict(record.to_dict()) for record in records]
@@ -174,8 +174,8 @@ def _ensure_worker(cfg: master.ProjectConfig) -> master.MasterManager:
174
174
  manager = master.MasterManager(configs, state_store=state_store)
175
175
 
176
176
  async def _run() -> None:
177
- """协程执行实际的 stop/start 流程。"""
178
- # 确保先停止旧实例(若存在)
177
+ """The coroutine performs the actual stop/start process."""
178
+ # Make sure to stop the old instance first(If it existsexist)
179
179
  try:
180
180
  await manager.stop_worker(cfg)
181
181
  except Exception:
@@ -187,20 +187,20 @@ def _ensure_worker(cfg: master.ProjectConfig) -> master.MasterManager:
187
187
 
188
188
 
189
189
  def main() -> int:
190
- """命令行入口,执行 master 健康检查并返回退出码。"""
190
+ """Command line entry, performs master health check and returns exit code."""
191
191
 
192
- parser = argparse.ArgumentParser(description="Master 启动后的健康检查")
193
- parser.add_argument("--project", default="hyphavibebotbackend", help="项目 slug bot 名称")
194
- parser.add_argument("--master-log", default=str(DEFAULT_MASTER_LOG), help="master 日志路径")
195
- parser.add_argument("--master-timeout", type=float, default=DEFAULT_TIMEOUT_MASTER, help="master 日志等待超时时间 ()")
196
- parser.add_argument("--probe-timeout", type=float, default=DEFAULT_TIMEOUT_PROBE, help="Telegram 探针超时时间 ()")
192
+ parser = argparse.ArgumentParser(description="Master Post-launch health check")
193
+ parser.add_argument("--project", default="hyphavibebotbackend", help="Project slug or bot name")
194
+ parser.add_argument("--master-log", default=str(DEFAULT_MASTER_LOG), help="master Log path")
195
+ parser.add_argument("--master-timeout", type=float, default=DEFAULT_TIMEOUT_MASTER, help="master Log wait timeout (Second)")
196
+ parser.add_argument("--probe-timeout", type=float, default=DEFAULT_TIMEOUT_PROBE, help="Telegram Probe timeout (Second)")
197
197
  args = parser.parse_args()
198
198
 
199
199
  project_id = master._sanitize_slug(args.project)
200
200
  master_log = Path(args.master_log)
201
201
 
202
202
  try:
203
- _wait_for_log_flag(master_log, "Master 已启动,监听管理员指令。", args.master_timeout)
203
+ _wait_for_log_flag(master_log, "Master Started, listening for administrator commands.", args.master_timeout)
204
204
  cfg = _load_project(project_id)
205
205
  manager = _ensure_worker(cfg)
206
206
  chat_id = _ensure_chat_id(cfg, manager)
@@ -208,12 +208,12 @@ def main() -> int:
208
208
  except Exception as exc:
209
209
  reason = str(exc)
210
210
  _notify_admins(reason)
211
- print(f"[healthcheck] 失败: {reason}", file=sys.stderr)
211
+ print(f"[healthcheck] fail: {reason}", file=sys.stderr)
212
212
  return 1
213
213
  else:
214
214
  print(
215
- "[healthcheck] 成功: master 已就绪,"
216
- f"worker={cfg.display_name} 启动完成,chat_id={chat_id},已发送探针消息"
215
+ "[healthcheck] success: master ready,"
216
+ f"worker={cfg.display_name} Startup completed, chat_id={chat_id}, Probe message sent"
217
217
  )
218
218
  return 0
219
219
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bash
2
- # ClaudeCode 模型配置
2
+ # ClaudeCode Model configuration
3
3
 
4
- # 将工作目录转换为 Claude CLI 默认的 project key
5
- # Claude 官方实现是简单地把绝对路径中的斜杠替换成连字符,并保留大小写。
4
+ # Convert the working directory to Claude CLI default project key.
5
+ # Claude The official implementation simply replaces slashes in absolute paths with hyphens, and preserve case.
6
6
  claude_project_key_from_workdir() {
7
7
  local path="$1"
8
8
  if [[ -z "$path" ]]; then
@@ -20,7 +20,7 @@ claude_project_key_from_workdir() {
20
20
  model_configure() {
21
21
  MODEL_NAME="ClaudeCode"
22
22
  MODEL_WORKDIR="${CLAUDE_WORKDIR:-${MODEL_WORKDIR:-$ROOT_DIR}}"
23
- # 默认关闭文件快照,避免孤儿 CLI 持续写入 jsonl
23
+ # File snapshot is turned off by default, avoid orphans CLI Continuous writing jsonl
24
24
  CLAUDE_DISABLE_FILE_CHECKPOINTING="${CLAUDE_DISABLE_FILE_CHECKPOINTING:-1}"
25
25
  CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING="${CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING:-$CLAUDE_DISABLE_FILE_CHECKPOINTING}"
26
26
  export CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING
scripts/models/codex.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # Codex 模型配置
2
+ # Codex Model configuration
3
3
 
4
4
  model_configure() {
5
5
  MODEL_NAME="codex"
scripts/models/common.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
- # 公共工具:模型脚本/运行脚本/停止脚本共享
2
+ # Public Tools: Model Scripts/run script/Stop script sharing
3
3
 
4
- # 避免重复定义时覆盖
4
+ # Avoid overwriting when repeating definitions
5
5
  if [[ -n "${_MODEL_COMMON_LOADED:-}" ]]; then
6
6
  return
7
7
  fi
@@ -9,10 +9,29 @@ _MODEL_COMMON_LOADED=1
9
9
 
10
10
  COMMON_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  ROOT_DIR="${ROOT_DIR:-$(cd "$COMMON_DIR/.." && pwd)}"
12
- LOG_ROOT="${LOG_ROOT:-$ROOT_DIR/logs}"
12
+ resolve_config_root() {
13
+ local raw=""
14
+ if [[ -n "${MASTER_CONFIG_ROOT:-}" ]]; then
15
+ raw="$MASTER_CONFIG_ROOT"
16
+ elif [[ -n "${VIBEGO_CONFIG_DIR:-}" ]]; then
17
+ raw="$VIBEGO_CONFIG_DIR"
18
+ elif [[ -n "${XDG_CONFIG_HOME:-}" ]]; then
19
+ raw="${XDG_CONFIG_HOME%/}/vibego"
20
+ else
21
+ raw="$HOME/.config/vibego"
22
+ fi
23
+ if [[ "$raw" == ~* ]]; then
24
+ printf '%s' "${raw/#\~/$HOME}"
25
+ else
26
+ printf '%s' "$raw"
27
+ fi
28
+ }
29
+
30
+ CONFIG_ROOT="${CONFIG_ROOT:-$(resolve_config_root)}"
31
+ LOG_ROOT="${LOG_ROOT:-$CONFIG_ROOT/logs}"
13
32
  TMUX_SESSION_PREFIX="${TMUX_SESSION_PREFIX:-vibe}"
14
33
 
15
- # 将任意路径/名称转换为 tmux/session 等安全的 slug
34
+ # Change any path/Name converted to tmux/session Wait for a safe slug
16
35
  sanitize_slug() {
17
36
  local input="$1"
18
37
  if [[ -z "$input" ]]; then
@@ -34,7 +53,7 @@ project_slug_from_workdir() {
34
53
  printf 'project'
35
54
  return
36
55
  fi
37
- # 将绝对路径改写为与 Claude 类似的 -Users-... 形式
56
+ # Rewrite the absolute path to something similar to Claude -Users-... form
38
57
  local replaced
39
58
  replaced=$(printf '%s' "$path" | sed 's#/#-#g')
40
59
  replaced="${replaced#-}"
@@ -87,4 +106,3 @@ find_latest_with_pattern() {
87
106
  done < <(find "$root" -type f -name "$pattern" -print0 2>/dev/null)
88
107
  [[ -n "$latest" ]] && printf '%s\n' "$latest"
89
108
  }
90
-
scripts/models/gemini.sh CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env bash
2
- # Gemini 模型占位配置(待实现)
2
+ # Gemini Model placeholder configuration (to be implemented)
3
3
 
4
4
  model_configure() {
5
5
  MODEL_NAME="gemini"
6
6
  MODEL_WORKDIR="${GEMINI_WORKDIR:-${MODEL_WORKDIR:-$ROOT_DIR}}"
7
- MODEL_CMD="${GEMINI_CMD:-echo 'gemini CLI 尚未配置'; sleep 1}"
7
+ MODEL_CMD="${GEMINI_CMD:-echo 'gemini CLI Not configured yet'; sleep 1}"
8
8
  MODEL_SESSION_ROOT="${GEMINI_SESSION_ROOT:-$LOG_ROOT/gemini-placeholder}"
9
9
  MODEL_SESSION_GLOB="${GEMINI_SESSION_GLOB:-*.jsonl}"
10
10
  MODEL_POINTER_BASENAME="${MODEL_POINTER_BASENAME:-current_session.txt}"
scripts/publish.sh CHANGED
@@ -1,33 +1,33 @@
1
1
  #!/usr/bin/env bash
2
- # VibeGo 完整发布脚本
3
- # 使用 keyring 进行 PyPI 认证,无需手动输入 token
2
+ # VibeGo Full release script
3
+ # Use keyring for PyPI authentication without manually entering tokens
4
4
  #
5
- # 前置条件:
6
- # 1. 已安装 keyring: pip install keyring
7
- # 2. 已存储 PyPI token keyring:
5
+ # Prerequisites:
6
+ # 1. keyring installed: pip install keyring
7
+ # 2. PyPI token stored in keyring:
8
8
  # python3.11 -c "import keyring; keyring.set_password('https://upload.pypi.org/legacy/', '__token__', 'your-token')"
9
9
  #
10
- # 使用方式:
11
- # ./scripts/publish.sh # 发布 patch 版本(默认)
12
- # ./scripts/publish.sh minor # 发布 minor 版本
13
- # ./scripts/publish.sh major # 发布 major 版本
10
+ # How to use:
11
+ # ./scripts/publish.sh # Publish patch version (default)
12
+ # ./scripts/publish.sh minor # Release minor version
13
+ # ./scripts/publish.sh major # Release major version
14
14
 
15
15
  set -e
16
16
 
17
- # 颜色定义
17
+ # color definition
18
18
  RED='\033[0;31m'
19
19
  GREEN='\033[0;32m'
20
20
  YELLOW='\033[1;33m'
21
21
  BLUE='\033[0;34m'
22
22
  NC='\033[0m' # No Color
23
23
 
24
- # 打印带颜色的消息
24
+ # Print colored messages
25
25
  print_info() {
26
26
  echo -e "${BLUE}ℹ️ $1${NC}"
27
27
  }
28
28
 
29
29
  print_success() {
30
- echo -e "${GREEN} $1${NC}"
30
+ echo -e "${GREEN}OK: $1${NC}"
31
31
  }
32
32
 
33
33
  print_warning() {
@@ -35,92 +35,92 @@ print_warning() {
35
35
  }
36
36
 
37
37
  print_error() {
38
- echo -e "${RED} $1${NC}"
38
+ echo -e "${RED}ERROR: $1${NC}"
39
39
  }
40
40
 
41
- # 项目根目录
41
+ # Project root directory
42
42
  PROJECT_ROOT="/Users/david/hypha/tools/vibeBot"
43
43
  cd "$PROJECT_ROOT"
44
44
 
45
- print_info "开始 VibeGo 发布流程..."
45
+ print_info "Start the VibeGo publishing process..."
46
46
  echo ""
47
47
 
48
- # 步骤 1: 检查 keyring 中是否存储了 PyPI token
49
- print_info "检查 keyring 配置..."
48
+ # Step 1: Check if PyPI token is stored in keyring
49
+ print_info "Check keyring configuration..."
50
50
  if ! python3.11 -c "import keyring; token = keyring.get_password('https://upload.pypi.org/legacy/', '__token__'); exit(0 if token else 1)" 2>/dev/null; then
51
- print_error "未在 keyring 中找到 PyPI token"
51
+ print_error "PyPI token not found in keyring"
52
52
  echo ""
53
- echo "请先执行以下命令存储 token"
53
+ echo "Please execute the following command to store the token first:"
54
54
  echo " python3.11 -c \"import keyring; keyring.set_password('https://upload.pypi.org/legacy/', '__token__', 'your-pypi-token')\""
55
55
  echo ""
56
56
  exit 1
57
57
  fi
58
- print_success "Keyring 配置正确"
58
+ print_success "Keyring Configured correctly"
59
59
  echo ""
60
60
 
61
- # 步骤 2: 创建/激活虚拟环境
62
- print_info "创建构建虚拟环境..."
61
+ # Step 2: create/Activate virtual environment
62
+ print_info "createBuild a virtual environment..."
63
63
  python3.11 -m venv ~/.venvs/vibego-build
64
64
  source ~/.venvs/vibego-build/bin/activate
65
- print_success "虚拟环境已激活"
65
+ print_success "Virtual environment is activated"
66
66
  echo ""
67
67
 
68
- # 步骤 3: 升级 pip 和安装构建工具
69
- print_info "安装构建依赖..."
68
+ # Step 3: Upgrade pip and install build tools
69
+ print_info "Install build dependencies..."
70
70
  pip install --upgrade pip build twine keyring > /dev/null 2>&1
71
- print_success "构建依赖已安装"
71
+ print_success "Build dependencies installed"
72
72
  echo ""
73
73
 
74
- # 步骤 4: 清理旧的构建产物
75
- print_info "清理旧的构建产物..."
74
+ # Step 4: Clean up old build artifacts
75
+ print_info "Clean up old build artifacts..."
76
76
  rm -rf "$PROJECT_ROOT/dist"
77
- print_success "构建产物已清理"
77
+ print_success "Build artifacts cleaned"
78
78
  echo ""
79
79
 
80
- # 步骤 5: 递增版本号
81
- VERSION_TYPE="${1:-patch}" # 默认为 patch
82
- print_info "递增版本号(类型:$VERSION_TYPE)..."
80
+ # Step 5: Increment version number
81
+ VERSION_TYPE="${1:-patch}" # Default is patch
82
+ print_info "Increment version number (type:$VERSION_TYPE)..."
83
83
  ./scripts/bump_version.sh "$VERSION_TYPE"
84
84
  echo ""
85
85
 
86
- # 步骤 6: 构建分发包
87
- print_info "构建 Python 分发包..."
86
+ # Step 6: Build distribution package
87
+ print_info "Build the Python distribution..."
88
88
  python3.11 -m build
89
- print_success "分发包构建完成"
89
+ print_success "The distribution package is built"
90
90
  echo ""
91
91
 
92
- # 步骤 7: 上传到 PyPI(使用 keyring 自动认证)
93
- print_info "上传到 PyPI(使用 keyring 认证)..."
92
+ # Step 7: Upload to PyPI (automatic authentication using keyring)
93
+ print_info "Upload to PyPI (using keyring authentication)..."
94
94
  twine upload dist/*
95
- print_success "已成功上传到 PyPI"
95
+ print_success "Successfully uploaded to PyPI"
96
96
  echo ""
97
97
 
98
- # 步骤 8: 清理并重装 pipx 中的 vibego
99
- print_info "更新本地 pipx 安装..."
98
+ # Step 8: Clean and reinstall vibego in pipx
99
+ print_info "Update local pipx installation..."
100
100
  rm -rf ~/.cache/pipx
101
101
  rm -rf ~/.local/pipx/venvs/vibego
102
102
  pipx install --python python3.11 vibego
103
103
  pipx upgrade vibego
104
- print_success "本地 vibego 已更新"
104
+ print_success "local vibego updated"
105
105
  echo ""
106
106
 
107
- # 步骤 9: 重启 vibego 服务
108
- print_info "重启 vibego 服务..."
109
- vibego stop || true # 忽略停止失败的错误
107
+ # Step 9: Restart vibego service
108
+ print_info "Restart vibego service..."
109
+ vibego stop || true # Ignore stop failure errors
110
110
  sleep 2
111
111
  vibego start
112
- print_success "vibego 服务已重启"
112
+ print_success "vibego Service has been restarted"
113
113
  echo ""
114
114
 
115
- # 完成
115
+ # Complete
116
116
  print_success "========================================="
117
- print_success "🎉 发布流程完成!"
117
+ print_success "🎉 The publishing process is complete!"
118
118
  print_success "========================================="
119
119
  echo ""
120
- print_info "后续步骤:"
121
- echo " 1. 推送 git 提交和标签:"
120
+ print_info "Next steps:"
121
+ echo " 1. Push git commits and tags:"
122
122
  echo " git push && git push --tags"
123
123
  echo ""
124
- echo " 2. 验证 PyPI 页面:"
124
+ echo " 2. Verify PyPI page:"
125
125
  echo " https://pypi.org/project/vibego/"
126
126
  echo ""
scripts/run_bot.sh CHANGED
@@ -1,11 +1,32 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
+ # shellcheck disable=SC2155
4
5
  SOURCE_ROOT="${VIBEGO_PACKAGE_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
5
- RUNTIME_ROOT="${VIBEGO_RUNTIME_ROOT:-$SOURCE_ROOT}"
6
+
7
+ resolve_config_root() {
8
+ local raw=""
9
+ if [[ -n "${MASTER_CONFIG_ROOT:-}" ]]; then
10
+ raw="$MASTER_CONFIG_ROOT"
11
+ elif [[ -n "${VIBEGO_CONFIG_DIR:-}" ]]; then
12
+ raw="$VIBEGO_CONFIG_DIR"
13
+ elif [[ -n "${XDG_CONFIG_HOME:-}" ]]; then
14
+ raw="${XDG_CONFIG_HOME%/}/vibego"
15
+ else
16
+ raw="$HOME/.config/vibego"
17
+ fi
18
+ if [[ "$raw" == ~* ]]; then
19
+ printf '%s' "${raw/#\~/$HOME}"
20
+ else
21
+ printf '%s' "$raw"
22
+ fi
23
+ }
24
+
25
+ CONFIG_ROOT="$(resolve_config_root)"
26
+ RUNTIME_ROOT="${VIBEGO_RUNTIME_ROOT:-$CONFIG_ROOT/runtime}"
6
27
  VENV_DIR="$RUNTIME_ROOT/.venv"
7
28
  MODELS_DIR="$SOURCE_ROOT/scripts/models"
8
- LOG_ROOT="${LOG_ROOT:-$RUNTIME_ROOT/logs}"
29
+ LOG_ROOT="${LOG_ROOT:-$CONFIG_ROOT/logs}"
9
30
  DEFAULT_LOG_FILE="$LOG_ROOT/run_bot.log"
10
31
  LOG_FILE="${LOG_FILE:-$DEFAULT_LOG_FILE}"
11
32
  MODEL_DEFAULT="${MODEL_DEFAULT:-codex}"
@@ -13,11 +34,11 @@ PROJECT_DEFAULT="${PROJECT_NAME:-}"
13
34
 
14
35
  usage() {
15
36
  cat <<USAGE
16
- 用法:${0##*/} [--model 名称] [--project 名称] [--foreground] [--no-stop]
17
- --model 启动指定模型 (codex|claudecode|gemini),默认: $MODEL_DEFAULT
18
- --project 指定项目别名,用于日志/会话区分
19
- --foreground 在前台运行(调试用),默认后台
20
- --no-stop 启动前不执行 stop_bot.sh(默认会先停旧实例)
37
+ usage:${0##*/} [--model name] [--project name] [--foreground] [--no-stop]
38
+ --model Start the specified model (codex|claudecode|gemini), default: $MODEL_DEFAULT
39
+ --project Specify project alias for logging/Conversation distinction
40
+ --foreground Run in foreground(for debugging), defaultBackstage
41
+ --no-stop Not executed before startup stop_bot.sh(defaultOld instances will be stopped first)
21
42
  USAGE
22
43
  }
23
44
 
@@ -39,7 +60,7 @@ while [[ $# -gt 0 ]]; do
39
60
  -h|--help)
40
61
  usage; exit 0 ;;
41
62
  *)
42
- echo "未知参数: $1" >&2
63
+ echo "unknown parameters: $1" >&2
43
64
  usage
44
65
  exit 1 ;;
45
66
  esac
@@ -47,14 +68,14 @@ done
47
68
 
48
69
  MODEL_SCRIPT="$MODELS_DIR/$MODEL.sh"
49
70
  if [[ ! -f "$MODEL_SCRIPT" ]]; then
50
- echo "[run-bot] 不支持的模型: $MODEL" >&2
71
+ echo "[run-bot] Unsupported model: $MODEL" >&2
51
72
  exit 1
52
73
  fi
53
74
 
54
- # 加载公共函数 + 模型配置
75
+ # Load public functions + Model configuration
55
76
  # shellcheck disable=SC1090
56
77
  source "$MODELS_DIR/common.sh"
57
- # 允许模型脚本重用环境变量
78
+ # Allow model scripts to reuse environment variables
58
79
  MODEL_WORKDIR="${MODEL_WORKDIR:-}"
59
80
  # shellcheck disable=SC1090
60
81
  source "$MODEL_SCRIPT"
@@ -83,24 +104,24 @@ expand_model_workdir() {
83
104
  MODEL_WORKDIR="$(expand_model_workdir "$MODEL_WORKDIR")"
84
105
 
85
106
  if [[ -z "$MODEL_WORKDIR" ]]; then
86
- echo "[run-bot] 配置缺少 MODEL_WORKDIR,请检查 config/projects.json" >&2
107
+ echo "[run-bot] Configuration is missing MODEL_WORKDIR, Please check config/projects.json" >&2
87
108
  exit 1
88
109
  fi
89
110
 
90
111
  if [[ ! -d "$MODEL_WORKDIR" ]]; then
91
- echo "[run-bot] 工作目录不存在: $MODEL_WORKDIR" >&2
112
+ echo "[run-bot] Working directory does not exist: $MODEL_WORKDIR" >&2
92
113
  exit 1
93
114
  fi
94
115
 
95
116
  if ! command -v tmux >/dev/null 2>&1; then
96
- echo "[run-bot] 未检测到 tmux,可通过 'brew install tmux' 安装" >&2
117
+ echo "[run-bot] tmux not detected, pass 'brew install tmux' Install" >&2
97
118
  exit 1
98
119
  fi
99
120
 
100
121
  if [[ -n "$MODEL_CMD" ]]; then
101
122
  IFS=' ' read -r MODEL_CMD_BIN _ <<<"$MODEL_CMD"
102
123
  if [[ -n "$MODEL_CMD_BIN" ]] && ! command -v "$MODEL_CMD_BIN" >/dev/null 2>&1; then
103
- echo "[run-bot] 未检测到模型命令: $MODEL_CMD_BIN" >&2
124
+ echo "[run-bot] Model command not detected: $MODEL_CMD_BIN" >&2
104
125
  exit 1
105
126
  fi
106
127
  fi
@@ -112,7 +133,7 @@ if (( FOREGROUND == 0 )); then
112
133
  CMD=("$0" --model "$MODEL" --project "$PROJECT_NAME" --foreground)
113
134
  (( NO_STOP )) && CMD+=(--no-stop)
114
135
  nohup "${CMD[@]}" >>"$RUN_LOG" 2>&1 &
115
- echo "[run-bot] 后台启动 (model=$MODEL project=$PROJECT_NAME) 日志: $RUN_LOG"
136
+ echo "[run-bot] Start in background (model=$MODEL project=$PROJECT_NAME) log: $RUN_LOG"
116
137
  exit 0
117
138
  fi
118
139
 
@@ -129,7 +150,7 @@ fi
129
150
  source "$VENV_DIR/bin/activate"
130
151
  REQUIREMENTS_PATH="${VIBEGO_REQUIREMENTS_PATH:-$SOURCE_ROOT/scripts/requirements.txt}"
131
152
  if [[ ! -f "$REQUIREMENTS_PATH" ]]; then
132
- echo "[run-bot] 未找到依赖清单: $REQUIREMENTS_PATH" >&2
153
+ echo "[run-bot] Dependency list not found: $REQUIREMENTS_PATH" >&2
133
154
  exit 1
134
155
  fi
135
156
  if [[ ! -f "$VENV_DIR/.requirements.installed" ]] || [[ "$REQUIREMENTS_PATH" -nt "$VENV_DIR/.requirements.installed" ]]; then