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.
- bot.py +1557 -1431
- logging_setup.py +25 -18
- master.py +799 -508
- project_repository.py +42 -40
- scripts/__init__.py +1 -2
- scripts/bump_version.sh +57 -55
- scripts/log_writer.py +19 -16
- scripts/master_healthcheck.py +44 -44
- scripts/models/claudecode.sh +4 -4
- scripts/models/codex.sh +1 -1
- scripts/models/common.sh +24 -6
- scripts/models/gemini.sh +2 -2
- scripts/publish.sh +50 -50
- scripts/run_bot.sh +38 -17
- scripts/start.sh +136 -116
- scripts/start_tmux_codex.sh +8 -8
- scripts/stop_all.sh +21 -21
- scripts/stop_bot.sh +31 -10
- scripts/test_deps_check.sh +32 -28
- tasks/__init__.py +1 -1
- tasks/commands.py +4 -4
- tasks/constants.py +1 -1
- tasks/fsm.py +9 -9
- tasks/models.py +7 -7
- tasks/service.py +56 -56
- vibego-1.0.0.dist-info/METADATA +236 -0
- {vibego-0.2.52.dist-info → vibego-1.0.0.dist-info}/RECORD +36 -35
- vibego-1.0.0.dist-info/licenses/LICENSE +201 -0
- vibego_cli/__init__.py +5 -4
- vibego_cli/__main__.py +1 -2
- vibego_cli/config.py +9 -9
- vibego_cli/deps.py +8 -9
- vibego_cli/main.py +63 -63
- vibego-0.2.52.dist-info/METADATA +0 -197
- {vibego-0.2.52.dist-info → vibego-1.0.0.dist-info}/WHEEL +0 -0
- {vibego-0.2.52.dist-info → vibego-1.0.0.dist-info}/entry_points.txt +0 -0
- {vibego-0.2.52.dist-info → vibego-1.0.0.dist-info}/top_level.txt +0 -0
vibego_cli/main.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""vibego
|
|
1
|
+
"""Entry point and subcommand implementations for the vibego CLI."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -27,32 +27,32 @@ BOTFATHER_URL = "https://core.telegram.org/bots#botfather"
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def _find_repo_root() -> Path:
|
|
30
|
-
"""
|
|
30
|
+
"""Determine the current repository root."""
|
|
31
31
|
|
|
32
32
|
return config.PACKAGE_ROOT
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def _prompt_token(default: Optional[str] = None) -> str:
|
|
36
|
-
"""
|
|
36
|
+
"""Interactively read the Telegram Bot token from stdin."""
|
|
37
37
|
|
|
38
|
-
prompt = "
|
|
38
|
+
prompt = "Enter the Master Bot token"
|
|
39
39
|
if default:
|
|
40
|
-
prompt +=
|
|
41
|
-
prompt += "
|
|
40
|
+
prompt += " (press Enter to keep the existing value)"
|
|
41
|
+
prompt += ": "
|
|
42
42
|
while True:
|
|
43
43
|
value = input(prompt).strip()
|
|
44
44
|
if not value and default:
|
|
45
45
|
value = default
|
|
46
46
|
if not value:
|
|
47
|
-
print("Token
|
|
47
|
+
print("Token cannot be empty. Follow the official guide if you need to create a bot:", BOTFATHER_URL)
|
|
48
48
|
continue
|
|
49
49
|
if TOKEN_PATTERN.match(value):
|
|
50
50
|
return value
|
|
51
|
-
print("
|
|
51
|
+
print("The token format looks invalid. Please verify and retry. Official instructions:", BOTFATHER_URL)
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _ensure_projects_assets() -> None:
|
|
55
|
-
"""
|
|
55
|
+
"""Ensure ``projects.json`` and ``master.db`` exist and are initialised."""
|
|
56
56
|
|
|
57
57
|
config.ensure_directories()
|
|
58
58
|
if not config.PROJECTS_JSON.exists():
|
|
@@ -61,7 +61,7 @@ def _ensure_projects_assets() -> None:
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _virtualenv_paths(venv_dir: Path) -> Tuple[Path, Path]:
|
|
64
|
-
"""
|
|
64
|
+
"""Return the Python and pip executables inside the virtual environment."""
|
|
65
65
|
|
|
66
66
|
if os.name == "nt":
|
|
67
67
|
bin_dir = venv_dir / "Scripts"
|
|
@@ -71,46 +71,46 @@ def _virtualenv_paths(venv_dir: Path) -> Tuple[Path, Path]:
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
def _ensure_virtualenv(repo_root: Path) -> Tuple[Path, Path]:
|
|
74
|
-
"""
|
|
74
|
+
"""Create or upgrade the runtime virtual environment and install dependencies."""
|
|
75
75
|
|
|
76
76
|
venv_dir = config.RUNTIME_DIR / "venv"
|
|
77
77
|
python_exec, pip_exec = _virtualenv_paths(venv_dir)
|
|
78
78
|
if not venv_dir.exists():
|
|
79
|
-
print("
|
|
79
|
+
print("Creating virtual environment:", venv_dir)
|
|
80
80
|
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
|
|
81
81
|
if not python_exec.exists():
|
|
82
|
-
raise RuntimeError(f"
|
|
82
|
+
raise RuntimeError(f"Virtual environment Python not found: {python_exec}")
|
|
83
83
|
if not pip_exec.exists():
|
|
84
|
-
raise RuntimeError(f"
|
|
84
|
+
raise RuntimeError(f"Virtual environment pip not found: {pip_exec}")
|
|
85
85
|
|
|
86
86
|
marker = venv_dir / ".requirements.timestamp"
|
|
87
87
|
req_file = config.ensure_worker_requirements_copy()
|
|
88
88
|
if not marker.exists() or req_file.stat().st_mtime > marker.stat().st_mtime:
|
|
89
|
-
print("
|
|
89
|
+
print("Installing Python dependencies (this may take a while)...")
|
|
90
90
|
install_requirements(req_file, pip_executable=pip_exec)
|
|
91
91
|
marker.touch()
|
|
92
92
|
return python_exec, pip_exec
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
def command_init(args: argparse.Namespace) -> None:
|
|
96
|
-
"""
|
|
96
|
+
"""Implementation of ``vibego init``."""
|
|
97
97
|
|
|
98
98
|
config.ensure_directories()
|
|
99
99
|
env_values = config.parse_env_file(config.ENV_FILE)
|
|
100
100
|
|
|
101
101
|
if not python_version_ok():
|
|
102
|
-
print("
|
|
102
|
+
print("Warning: running on Python earlier than 3.11; upgrade for full functionality.")
|
|
103
103
|
|
|
104
104
|
missing = check_cli_dependencies()
|
|
105
105
|
if missing:
|
|
106
|
-
print("
|
|
106
|
+
print("Missing dependencies detected:")
|
|
107
107
|
for item in missing:
|
|
108
108
|
print("-", item)
|
|
109
|
-
print("
|
|
109
|
+
print("Install the listed dependencies and rerun the command.")
|
|
110
110
|
return
|
|
111
111
|
|
|
112
112
|
if config.ENV_FILE.exists() and not args.force:
|
|
113
|
-
print("
|
|
113
|
+
print(".env already exists. Use --force to overwrite.")
|
|
114
114
|
default_token = env_values.get("MASTER_BOT_TOKEN")
|
|
115
115
|
token = args.token or _prompt_token(default_token)
|
|
116
116
|
env_values["MASTER_BOT_TOKEN"] = token
|
|
@@ -122,25 +122,25 @@ def command_init(args: argparse.Namespace) -> None:
|
|
|
122
122
|
config.dump_env_file(config.ENV_FILE, env_values)
|
|
123
123
|
_ensure_projects_assets()
|
|
124
124
|
|
|
125
|
-
print("
|
|
126
|
-
print("
|
|
127
|
-
print(f" 1.
|
|
128
|
-
print(" 2.
|
|
125
|
+
print("Initialisation complete. Configuration directory:", config.CONFIG_ROOT)
|
|
126
|
+
print("Next steps:")
|
|
127
|
+
print(f" 1. Edit {config.ENV_FILE} to configure proxy settings if needed.")
|
|
128
|
+
print(" 2. Run `vibego start` to launch the master service.")
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
def _load_env_or_fail() -> Dict[str, str]:
|
|
132
|
-
"""
|
|
132
|
+
"""Read ``.env`` and raise when initialisation has not been performed."""
|
|
133
133
|
|
|
134
134
|
if not config.ENV_FILE.exists():
|
|
135
|
-
raise RuntimeError(f"
|
|
135
|
+
raise RuntimeError(f"{config.ENV_FILE} not found. Please run `vibego init` first.")
|
|
136
136
|
values = config.parse_env_file(config.ENV_FILE)
|
|
137
137
|
if "MASTER_BOT_TOKEN" not in values or not values["MASTER_BOT_TOKEN"].strip():
|
|
138
|
-
raise RuntimeError("MASTER_BOT_TOKEN
|
|
138
|
+
raise RuntimeError("MASTER_BOT_TOKEN is missing. Rerun `vibego init`.")
|
|
139
139
|
return values
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
def _build_master_env(base_env: Dict[str, str]) -> Dict[str, str]:
|
|
143
|
-
"""
|
|
143
|
+
"""Construct the environment variables required by ``master.py``."""
|
|
144
144
|
|
|
145
145
|
env = os.environ.copy()
|
|
146
146
|
env.update(base_env)
|
|
@@ -164,13 +164,13 @@ def _build_master_env(base_env: Dict[str, str]) -> Dict[str, str]:
|
|
|
164
164
|
|
|
165
165
|
|
|
166
166
|
def _write_pid(pid: int) -> None:
|
|
167
|
-
"""
|
|
167
|
+
"""Persist the master process PID."""
|
|
168
168
|
|
|
169
169
|
config.MASTER_PID_FILE.write_text(str(pid), encoding="utf-8")
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def _read_pid() -> Optional[int]:
|
|
173
|
-
"""
|
|
173
|
+
"""Return the persisted master PID if present."""
|
|
174
174
|
|
|
175
175
|
if not config.MASTER_PID_FILE.exists():
|
|
176
176
|
return None
|
|
@@ -179,40 +179,40 @@ def _read_pid() -> Optional[int]:
|
|
|
179
179
|
|
|
180
180
|
|
|
181
181
|
def command_start(args: argparse.Namespace) -> None:
|
|
182
|
-
"""
|
|
182
|
+
"""Implementation of ``vibego start``."""
|
|
183
183
|
|
|
184
184
|
env_values = _load_env_or_fail()
|
|
185
185
|
_ensure_projects_assets()
|
|
186
186
|
|
|
187
187
|
if not python_version_ok():
|
|
188
188
|
raise RuntimeError(
|
|
189
|
-
"
|
|
190
|
-
"
|
|
189
|
+
"Python earlier than 3.11 cannot run the master. "
|
|
190
|
+
"Upgrade via `brew install python@3.11` or another method."
|
|
191
191
|
)
|
|
192
192
|
|
|
193
193
|
missing = check_cli_dependencies()
|
|
194
194
|
if missing:
|
|
195
|
-
print("
|
|
195
|
+
print("Missing dependencies detected:")
|
|
196
196
|
for item in missing:
|
|
197
197
|
print("-", item)
|
|
198
|
-
print("
|
|
198
|
+
print("Install the listed dependencies before retrying.")
|
|
199
199
|
return
|
|
200
200
|
|
|
201
201
|
repo_root = _find_repo_root()
|
|
202
202
|
try:
|
|
203
203
|
python_exec, _ = _ensure_virtualenv(repo_root)
|
|
204
204
|
except subprocess.CalledProcessError as exc:
|
|
205
|
-
raise RuntimeError(f"
|
|
205
|
+
raise RuntimeError(f"Virtual environment initialisation failed: {exc}") from exc
|
|
206
206
|
|
|
207
207
|
master_env = _build_master_env(env_values)
|
|
208
208
|
log_file = config.LOG_FILE
|
|
209
209
|
log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
210
210
|
|
|
211
211
|
if _read_pid():
|
|
212
|
-
print("
|
|
212
|
+
print("Master already running. Execute `vibego stop` before restarting.")
|
|
213
213
|
return
|
|
214
214
|
|
|
215
|
-
print("
|
|
215
|
+
print("Starting master service...")
|
|
216
216
|
with open(log_file, "a", encoding="utf-8") as log_fp:
|
|
217
217
|
process = subprocess.Popen(
|
|
218
218
|
[str(python_exec), "master.py"],
|
|
@@ -226,26 +226,26 @@ def command_start(args: argparse.Namespace) -> None:
|
|
|
226
226
|
|
|
227
227
|
time.sleep(2)
|
|
228
228
|
if process.poll() is not None:
|
|
229
|
-
raise RuntimeError("
|
|
229
|
+
raise RuntimeError("Master process failed to start. Check the logs.")
|
|
230
230
|
|
|
231
|
-
print("
|
|
232
|
-
print("
|
|
233
|
-
print("
|
|
231
|
+
print("Master started. PID:", process.pid)
|
|
232
|
+
print("Log file:", log_file)
|
|
233
|
+
print("Send /start to the bot in Telegram to complete authorisation.")
|
|
234
234
|
|
|
235
235
|
|
|
236
236
|
def command_stop(args: argparse.Namespace) -> None:
|
|
237
|
-
"""
|
|
237
|
+
"""Implementation of ``vibego stop``."""
|
|
238
238
|
|
|
239
239
|
pid = _read_pid()
|
|
240
240
|
if not pid:
|
|
241
|
-
print("
|
|
241
|
+
print("Master process not detected.")
|
|
242
242
|
return
|
|
243
243
|
|
|
244
|
-
print("
|
|
244
|
+
print("Stopping master (PID =", pid, ")...")
|
|
245
245
|
try:
|
|
246
246
|
os.kill(pid, signal.SIGTERM)
|
|
247
247
|
except ProcessLookupError:
|
|
248
|
-
print("
|
|
248
|
+
print("Process not found; treating as already stopped.")
|
|
249
249
|
else:
|
|
250
250
|
for _ in range(20):
|
|
251
251
|
time.sleep(0.5)
|
|
@@ -254,13 +254,13 @@ def command_stop(args: argparse.Namespace) -> None:
|
|
|
254
254
|
except ProcessLookupError:
|
|
255
255
|
break
|
|
256
256
|
else:
|
|
257
|
-
print("
|
|
257
|
+
print("Master did not exit within the expected time. Please investigate manually.")
|
|
258
258
|
config.MASTER_PID_FILE.unlink(missing_ok=True)
|
|
259
|
-
print("
|
|
259
|
+
print("Stop completed.")
|
|
260
260
|
|
|
261
261
|
|
|
262
262
|
def command_status(args: argparse.Namespace) -> None:
|
|
263
|
-
"""
|
|
263
|
+
"""Implementation of ``vibego status``."""
|
|
264
264
|
|
|
265
265
|
env_values = config.parse_env_file(config.ENV_FILE)
|
|
266
266
|
pid = _read_pid()
|
|
@@ -289,7 +289,7 @@ def command_status(args: argparse.Namespace) -> None:
|
|
|
289
289
|
|
|
290
290
|
|
|
291
291
|
def command_doctor(args: argparse.Namespace) -> None:
|
|
292
|
-
"""
|
|
292
|
+
"""Implementation of ``vibego doctor``. Outputs a diagnostic report."""
|
|
293
293
|
|
|
294
294
|
report = {
|
|
295
295
|
"python_version": sys.version,
|
|
@@ -305,44 +305,44 @@ def command_doctor(args: argparse.Namespace) -> None:
|
|
|
305
305
|
|
|
306
306
|
|
|
307
307
|
def build_parser() -> argparse.ArgumentParser:
|
|
308
|
-
"""
|
|
308
|
+
"""Build the top-level argparse parser."""
|
|
309
309
|
|
|
310
|
-
parser = argparse.ArgumentParser(prog="vibego", description="vibego CLI
|
|
310
|
+
parser = argparse.ArgumentParser(prog="vibego", description="vibego CLI utilities")
|
|
311
311
|
parser.add_argument(
|
|
312
312
|
"--config-dir",
|
|
313
313
|
dest="config_dir",
|
|
314
|
-
help="
|
|
314
|
+
help="Custom configuration directory (default ~/.config/vibego)",
|
|
315
315
|
)
|
|
316
316
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
317
317
|
|
|
318
|
-
init_parser = subparsers.add_parser("init", help="
|
|
319
|
-
init_parser.add_argument("--token", help="
|
|
320
|
-
init_parser.add_argument("--force", action="store_true", help="
|
|
318
|
+
init_parser = subparsers.add_parser("init", help="Initialise the configuration directory and master token")
|
|
319
|
+
init_parser.add_argument("--token", help="Provide the master bot token directly to avoid interactive input")
|
|
320
|
+
init_parser.add_argument("--force", action="store_true", help="Overwrite the existing .env file")
|
|
321
321
|
init_parser.set_defaults(func=command_init)
|
|
322
322
|
|
|
323
|
-
start_parser = subparsers.add_parser("start", help="
|
|
323
|
+
start_parser = subparsers.add_parser("start", help="Start the master service")
|
|
324
324
|
start_parser.set_defaults(func=command_start)
|
|
325
325
|
|
|
326
|
-
stop_parser = subparsers.add_parser("stop", help="
|
|
326
|
+
stop_parser = subparsers.add_parser("stop", help="Stop the master service")
|
|
327
327
|
stop_parser.set_defaults(func=command_stop)
|
|
328
328
|
|
|
329
|
-
status_parser = subparsers.add_parser("status", help="
|
|
329
|
+
status_parser = subparsers.add_parser("status", help="Display the current running status")
|
|
330
330
|
status_parser.set_defaults(func=command_status)
|
|
331
331
|
|
|
332
|
-
doctor_parser = subparsers.add_parser("doctor", help="
|
|
332
|
+
doctor_parser = subparsers.add_parser("doctor", help="Run dependency and configuration diagnostics")
|
|
333
333
|
doctor_parser.set_defaults(func=command_doctor)
|
|
334
334
|
|
|
335
335
|
return parser
|
|
336
336
|
|
|
337
337
|
|
|
338
338
|
def main(argv: Optional[Sequence[str]] = None) -> None:
|
|
339
|
-
"""CLI
|
|
339
|
+
"""CLI main entrypoint."""
|
|
340
340
|
|
|
341
341
|
parser = build_parser()
|
|
342
342
|
args = parser.parse_args(argv)
|
|
343
343
|
if args.config_dir:
|
|
344
344
|
os.environ["VIBEGO_CONFIG_DIR"] = args.config_dir
|
|
345
|
-
#
|
|
345
|
+
# Reload path configuration after overriding the config directory.
|
|
346
346
|
from importlib import reload
|
|
347
347
|
|
|
348
348
|
reload(config)
|
|
@@ -350,7 +350,7 @@ def main(argv: Optional[Sequence[str]] = None) -> None:
|
|
|
350
350
|
try:
|
|
351
351
|
args.func(args)
|
|
352
352
|
except Exception as exc: # pylint: disable=broad-except
|
|
353
|
-
print("
|
|
353
|
+
print("Execution failed:", exc)
|
|
354
354
|
sys.exit(1)
|
|
355
355
|
|
|
356
356
|
|
vibego-0.2.52.dist-info/METADATA
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: vibego
|
|
3
|
-
Version: 0.2.52
|
|
4
|
-
Summary: vibego CLI:用于初始化与管理 Telegram Master Bot 的工具
|
|
5
|
-
Author: Hypha
|
|
6
|
-
License-Expression: LicenseRef-Proprietary
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
-
Classifier: Operating System :: MacOS
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: Topic :: Software Development :: Build Tools
|
|
12
|
-
Classifier: Environment :: Console
|
|
13
|
-
Requires-Python: >=3.11
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
Requires-Dist: aiogram<4.0.0,>=3.0.0
|
|
16
|
-
Requires-Dist: aiohttp-socks>=0.10.0
|
|
17
|
-
Requires-Dist: aiosqlite>=0.19.0
|
|
18
|
-
Requires-Dist: markdown-it-py<4.0.0,>=3.0.0
|
|
19
|
-
|
|
20
|
-
# vibe-bot(Telegram → Mac CLI → Telegram 回推)
|
|
21
|
-
|
|
22
|
-
## 环境依赖
|
|
23
|
-
|
|
24
|
-
- 建议使用 Homebrew 安装核心命令行工具,保证脚本依赖一致:
|
|
25
|
-
```bash
|
|
26
|
-
brew install python3 tmux codex
|
|
27
|
-
```
|
|
28
|
-
Homebrew 官方文档说明可以通过 `brew install` 安装 Python 及 tmux,Codex CLI 官方文档同样推荐使用 Homebrew。安装完成后可执行
|
|
29
|
-
`python3 --version`、`tmux -V` 和 `codex --version` 验证环境。
|
|
30
|
-
- 首次使用 Codex CLI 需通过 ChatGPT 登录:
|
|
31
|
-
```bash
|
|
32
|
-
codex login
|
|
33
|
-
```
|
|
34
|
-
登录成功后会在本地写入凭据(默认为 `~/.codex/auth.json`)。若需使用 API Key,可执行 `codex login --api-key <key>`。
|
|
35
|
-
- 项目脚本默认调用 Homebrew 提供的 `python3`。若需要隔离依赖,建议提前创建虚拟环境:
|
|
36
|
-
```bash
|
|
37
|
-
python3 -m venv .venv
|
|
38
|
-
source .venv/bin/activate
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## 目录结构
|
|
42
|
-
|
|
43
|
-
- `bot.py`:aiogram 3 worker,支持多模型会话解析(Codex / ClaudeCode / 预留 Gemini)。
|
|
44
|
-
- `scripts/run_bot.sh`:一键启动脚本(自动建 venv、启动 tmux + 模型 CLI + bot)。
|
|
45
|
-
- `scripts/stop_bot.sh`:终止当前项目 worker(tmux + bot 进程)。
|
|
46
|
-
- `scripts/start_tmux_codex.sh`:底层 tmux/CLI 启动器,被 `run_bot.sh` 调用,默认以 `tmux -u` 强制启用 UTF-8。
|
|
47
|
-
- `scripts/models/`:模型配置模块(`common.sh`/`codex.sh`/`claudecode.sh`/`gemini.sh`)。
|
|
48
|
-
- `logs/<model>/<project>/`:运行日志(`run_bot.log`、`model.log`、`bot.pid`、`current_session.txt`)。
|
|
49
|
-
- `model.log` 由 `scripts/log_writer.py` 控制,单文件上限 20MB,仅保留最近 24 小时的归档(可通过 `MODEL_LOG_MAX_BYTES`、
|
|
50
|
-
`MODEL_LOG_RETENTION_SECONDS` 覆盖)。
|
|
51
|
-
- `.env.example`:环境配置模板(复制为 `.env` 后按需修改)。
|
|
52
|
-
|
|
53
|
-
## 快速开始
|
|
54
|
-
|
|
55
|
-
建议通过 PyPI 安装的 `vibego` 命令完成初始化与启动,示例:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
pipx install vibego # 或者 pip install --user vibego
|
|
59
|
-
vibego init # 初始化配置目录并写入 Master Bot Token
|
|
60
|
-
vibego start # 启动 master 服务
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
若在本仓库内调试,可执行:
|
|
64
|
-
|
|
65
|
-
1. 安装依赖:`brew install python tmux`(若需要代理,请提前配置)。
|
|
66
|
-
2. 初始化配置:`python -m vibego_cli init` 或 `./scripts/vibego init`,按提示输入 Telegram Master Bot Token。
|
|
67
|
-
- 初始化会在 `~/.config/vibego/` 下创建 `.env`、`config/projects.json`、`config/master.db` 等文件。
|
|
68
|
-
3. 启动 master:`python -m vibego_cli start`。启动后请在 Telegram 中向 Bot 发送 `/start` 完成授权。
|
|
69
|
-
4. 查看状态或停止服务:运行 `python -m vibego_cli status`、`python -m vibego_cli stop`。
|
|
70
|
-
|
|
71
|
-
> CLI 会自动安装 Python 依赖并在 `~/.config/vibego/` 下准备 `logs/`、`state/` 等运行期目录,避免污染仓库工作区。
|
|
72
|
-
|
|
73
|
-
## 日志 & 目录
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
logs/
|
|
77
|
-
└─ codex/
|
|
78
|
-
└─ mall-backend/
|
|
79
|
-
├─ run_bot.log # run_bot.sh 输出
|
|
80
|
-
├─ model.log # tmux pipe-pane 捕获的模型 CLI 输出
|
|
81
|
-
├─ bot.pid # 当前 bot 进程 PID(stop_bot.sh 使用)
|
|
82
|
-
└─ current_session.txt # 最近一次 JSONL 会话指针
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## 模型切换
|
|
86
|
-
|
|
87
|
-
- 支持参数:`codex`、`claudecode`、`gemini`(占位)。
|
|
88
|
-
- 切换流程:`stop_bot.sh --model <旧>` → `run_bot.sh --model <新>`。
|
|
89
|
-
- 每个模型在 `scripts/models/<model>.sh` 中维护独立配置,互不依赖;公共逻辑位于 `scripts/models/common.sh`。
|
|
90
|
-
- `ACTIVE_MODEL` 会在 `/start` 回复及日志中显示,并写入环境变量供 `bot.py` 使用。
|
|
91
|
-
|
|
92
|
-
### Codex
|
|
93
|
-
|
|
94
|
-
| 变量 | 说明 |
|
|
95
|
-
|----------------------|-----------------------------------------------|
|
|
96
|
-
| `CODEX_WORKDIR` | Codex CLI 工作目录(默认 `.env` 中自定义或 fallback ROOT) |
|
|
97
|
-
| `CODEX_CMD` | 启动命令,默认 `codex --dangerously-bypass-...` |
|
|
98
|
-
| `CODEX_SESSION_ROOT` | JSONL 根目录(默认 `~/.codex/sessions`) |
|
|
99
|
-
| `CODEX_SESSION_GLOB` | JSONL 文件匹配(默认 `rollout-*.jsonl`) |
|
|
100
|
-
|
|
101
|
-
### ClaudeCode
|
|
102
|
-
|
|
103
|
-
| 变量 | 说明 |
|
|
104
|
-
|-----------------------|---------------------------------------|
|
|
105
|
-
| `CLAUDE_WORKDIR` | 工程目录(默认与 Codex 相同) |
|
|
106
|
-
| `CLAUDE_CMD` | CLI 启动命令,示例 `claude --project <path>` |
|
|
107
|
-
| `CLAUDE_PROJECT_ROOT` | JSONL 根目录(默认 `~/.claude/projects`) |
|
|
108
|
-
| `CLAUDE_SESSION_GLOB` | JSONL 文件匹配(默认 `*.jsonl`) |
|
|
109
|
-
| `CLAUDE_PROJECT_KEY` | 可选:显式指定 `~/.claude/projects/<key>` 路径 |
|
|
110
|
-
|
|
111
|
-
### Gemini(预留)
|
|
112
|
-
|
|
113
|
-
- `scripts/models/gemini.sh` 暂使用占位命令,可在后续接入官方 CLI 时扩展。
|
|
114
|
-
|
|
115
|
-
## aiogram Worker 行为
|
|
116
|
-
|
|
117
|
-
- `/start`:返回 `chat_id`、`MODE`、`ACTIVE_MODEL`;日志打印 `chat_id` 与 `user_id`。
|
|
118
|
-
- 文本消息:
|
|
119
|
-
1. 依据 `ACTIVE_MODEL` 选择 `SessionAdapter`,读取 `current_session.txt` 中记录的 JSONL 文件,必要时搜索
|
|
120
|
-
`MODEL_SESSION_ROOT` 以回填。
|
|
121
|
-
2. 将 prompt 注入 tmux(发送 `Esc` 清空模式、`C-j` 换行、`Enter` 提交)。
|
|
122
|
-
3. 首次读取 `SESSION_OFFSETS` 初始化偏移;随后通过 `_deliver_pending_messages()` 补发当前尾部内容并持续轮询 JSONL。
|
|
123
|
-
4. watcher 阶段提示 `ACTIVE_MODEL` 正在处理中,完成后自动推送结果(保留 Markdown)。
|
|
124
|
-
- MODE=A 下仍支持 `AGENT_CMD` 直接执行 CLI。
|
|
125
|
-
|
|
126
|
-
## 新增脚本
|
|
127
|
-
|
|
128
|
-
- `run_bot.sh`
|
|
129
|
-
- `--model <name>`:codex / claudecode / gemini。
|
|
130
|
-
- `--project <slug>`:日志/会话目录名称;未提供时依据工作目录推导。
|
|
131
|
-
- `--foreground`:前台运行(默认后台 + `nohup`)。
|
|
132
|
-
- `--no-stop`:启动前跳过 stop(默认先执行 `stop_bot.sh` 保证幂等)。
|
|
133
|
-
- `stop_bot.sh`
|
|
134
|
-
- 幂等终止:`tmux kill-session`、关闭 `bot.pid` 指向的进程、移除缓存。
|
|
135
|
-
- 示例:`./scripts/stop_bot.sh --model codex --project mall-backend`。
|
|
136
|
-
|
|
137
|
-
## 配置要点
|
|
138
|
-
|
|
139
|
-
### `.env`(Master 全局配置)
|
|
140
|
-
|
|
141
|
-
- 文件位置:`~/.config/vibego/.env`(可通过环境变量 `VIBEGO_CONFIG_DIR` 自定义)。
|
|
142
|
-
- `MASTER_BOT_TOKEN`:master bot 的 Token,由 `vibego init` 引导输入,启动时必须存在。
|
|
143
|
-
- `MASTER_CHAT_ID` / `MASTER_USER_ID`:首次在 Telegram 与 master 交互时自动写入,表示已授权的管理员账号。
|
|
144
|
-
- `MASTER_WHITELIST`:逗号分隔的 chat_id 列表,留空表示不限制;若与自动写入冲突以最新值为准。
|
|
145
|
-
- 其他可选变量(代理、日志级别、默认模型等)可按需新增,未设置时脚本使用默认值。
|
|
146
|
-
|
|
147
|
-
- 项目配置持久化在 `~/.config/vibego/config/master.db`(SQLite),对应的 JSON 镜像为
|
|
148
|
-
`~/.config/vibego/config/projects.json`。如需离线编辑,可参考仓库内的 `config/projects.json.example` 模板。
|
|
149
|
-
- Master「⚙️ 项目管理」可新增/编辑/删除项目;仍可离线编辑 JSON,启动时会自动导入并同步至数据库。
|
|
150
|
-
- 必填字段:`bot_name`、`bot_token`、`project_slug`、`default_model`。
|
|
151
|
-
- 可选字段:`workdir`(项目路径)、`allowed_chat_id`(用于预设授权)。留空时,worker 首次收到消息会自动记录 chat_id 并写回
|
|
152
|
-
`~/.config/vibego/state/master_state.json`。
|
|
153
|
-
- 其他自定义字段暂不读取。
|
|
154
|
-
|
|
155
|
-
### 自动授权 & 状态
|
|
156
|
-
|
|
157
|
-
- worker 启动时若 `allowed_chat_id` 为空,首次合法消息会写入 `state/state.json` 并立即生效。
|
|
158
|
-
- master 重启:先调用 `stop_bot.sh` 清理,再依据 state 还原正在运行的项目。
|
|
159
|
-
|
|
160
|
-
## 后续规划
|
|
161
|
-
|
|
162
|
-
- Master bot(8031153139:AAF83jNsfzLTk428HAOVo0pJgHadisxkhCo)将统一轮询多个项目 bot,并调用 run/stop 脚本管理
|
|
163
|
-
worker;当前版本先提供 worker 端结构与日志规范。
|
|
164
|
-
- Gemini CLI 接入待官方方案确定后补充。
|
|
165
|
-
|
|
166
|
-
## 注意
|
|
167
|
-
|
|
168
|
-
- `~/.config/vibego/.env` 内包含敏感 Token 与管理员信息,请勿提交至版本库。
|
|
169
|
-
- 若需减少日志体积,可按需清理 `logs/<model>/<project>/` 或调整脚本输出阈值。
|
|
170
|
-
|
|
171
|
-
## Master 控制
|
|
172
|
-
|
|
173
|
-
- 管理员 Bot 使用 `MASTER_BOT_TOKEN` 启动(运行 `python master.py`)。
|
|
174
|
-
- 项目列表由 Master 仓库(`~/.config/vibego/config/master.db`)维护,可通过项目管理按钮或
|
|
175
|
-
`~/.config/vibego/config/projects.json` 同步文件更新。示例字段:
|
|
176
|
-
- `bot_name`:对应 Telegram 机器人的用户名(可带或不带 `@`,展示与交互时自动加 `@`)
|
|
177
|
-
- `bot_token`:对应 worker 的 Telegram Token
|
|
178
|
-
- `default_model`:默认模型(codex / claudecode / gemini)
|
|
179
|
-
- `project_slug`:日志/目录名称
|
|
180
|
-
- `workdir`:项目工作目录(可选)
|
|
181
|
-
- `allowed_chat_id`:项目 worker 的授权 chat(用于 run_bot 时注入环境)
|
|
182
|
-
- 状态持久化:`~/.config/vibego/state/master_state.json` 自动记录各项目当前模型与运行状态,master 重启时会先 `stop_bot.sh`
|
|
183
|
-
清理现场,再根据状态恢复。
|
|
184
|
-
|
|
185
|
-
### 管理命令
|
|
186
|
-
|
|
187
|
-
| 命令 | 说明 |
|
|
188
|
-
|-----------------------------|--------------------------------|
|
|
189
|
-
| `/projects` | 列出所有项目当前状态与模型 |
|
|
190
|
-
| `/run <project> [model]` | 启动指定项目 worker,模型可选(默认使用当前/配置值) |
|
|
191
|
-
| `/stop <project>` | 停止项目 worker |
|
|
192
|
-
| `/switch <project> <model>` | 停止后以新模型重新启动 |
|
|
193
|
-
| `/start` | 显示帮助与项目数量 |
|
|
194
|
-
|
|
195
|
-
- `<project>` 参数可填写 `project_slug` 或对应 `@bot_name`,命令回复将自动展示可点击的 `@` 链接。
|
|
196
|
-
|
|
197
|
-
> master 仅与管理员 bot 交互;项目 bot 仍由 worker(run_bot.sh 启动的 `bot.py`)负责处理业务消息。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|