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
scripts/start.sh
CHANGED
|
@@ -3,6 +3,9 @@ set -eo pipefail
|
|
|
3
3
|
|
|
4
4
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
5
|
MASTER_CONFIG_ROOT="${MASTER_CONFIG_ROOT:-$HOME/.config/vibego}"
|
|
6
|
+
RUNTIME_DIR="${VIBEGO_RUNTIME_ROOT:-$MASTER_CONFIG_ROOT/runtime}"
|
|
7
|
+
VENV_DIR="$RUNTIME_DIR/.venv"
|
|
8
|
+
LEGACY_VENV_DIR="$ROOT_DIR/.venv"
|
|
6
9
|
STATE_DIR="$MASTER_CONFIG_ROOT/state"
|
|
7
10
|
LOG_DIR="$MASTER_CONFIG_ROOT/logs"
|
|
8
11
|
LOCK_FILE="$STATE_DIR/master_restart.lock"
|
|
@@ -10,8 +13,8 @@ START_LOG="$LOG_DIR/start.log"
|
|
|
10
13
|
CODEX_STAMP_FILE="$STATE_DIR/npm_codex_install.stamp"
|
|
11
14
|
CODEX_INSTALL_TTL="${CODEX_INSTALL_TTL:-86400}"
|
|
12
15
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
16
|
+
# Unified restart signal file path: use the configuration directory instead of the code directory
|
|
17
|
+
# In this way, the master installed by pipx and the master run from the source code can share the same signal file.
|
|
15
18
|
export MASTER_RESTART_SIGNAL_PATH="$STATE_DIR/restart_signal.json"
|
|
16
19
|
export LOG_ROOT="${LOG_ROOT:-$LOG_DIR}"
|
|
17
20
|
if [[ -z "${LOG_FILE:-}" ]]; then
|
|
@@ -42,34 +45,35 @@ cd "$ROOT_DIR"
|
|
|
42
45
|
|
|
43
46
|
mkdir -p "$(dirname "$LOCK_FILE")"
|
|
44
47
|
mkdir -p "$(dirname "$START_LOG")"
|
|
48
|
+
mkdir -p "$RUNTIME_DIR"
|
|
45
49
|
touch "$START_LOG"
|
|
46
50
|
exec >>"$START_LOG"
|
|
47
51
|
exec 2>&1
|
|
48
52
|
|
|
49
|
-
log_info "start.sh
|
|
53
|
+
log_info "start.sh start, pid=$$"
|
|
50
54
|
|
|
51
55
|
if [[ -f "$LOCK_FILE" ]]; then
|
|
52
|
-
log_error "
|
|
56
|
+
log_error "Already have start.sh During execution, skip this startup."
|
|
53
57
|
exit 1
|
|
54
58
|
fi
|
|
55
59
|
|
|
56
60
|
printf '%d\n' $$ > "$LOCK_FILE"
|
|
57
61
|
|
|
58
|
-
log_info "
|
|
62
|
+
log_info "Lock file created:$LOCK_FILE"
|
|
59
63
|
|
|
60
64
|
ensure_codex_installed() {
|
|
61
65
|
local need_install=1
|
|
62
66
|
local now
|
|
63
67
|
local codex_bin
|
|
64
68
|
if ! command -v npm >/dev/null 2>&1; then
|
|
65
|
-
log_error "
|
|
69
|
+
log_error "npm not detected, executable missing, skipped @openai/codex Global installation"
|
|
66
70
|
return
|
|
67
71
|
fi
|
|
68
72
|
|
|
69
|
-
log_info "
|
|
73
|
+
log_info "npm version detected:$(npm --version)"
|
|
70
74
|
|
|
71
75
|
if [[ ! "$CODEX_INSTALL_TTL" =~ ^[0-9]+$ ]]; then
|
|
72
|
-
log_error "CODEX_INSTALL_TTL
|
|
76
|
+
log_error "CODEX_INSTALL_TTL Illegal value:$CODEX_INSTALL_TTL, Fallback to 86400 seconds"
|
|
73
77
|
CODEX_INSTALL_TTL=86400
|
|
74
78
|
fi
|
|
75
79
|
|
|
@@ -99,11 +103,11 @@ ensure_codex_installed() {
|
|
|
99
103
|
fi
|
|
100
104
|
|
|
101
105
|
if (( need_install )); then
|
|
102
|
-
log_info "
|
|
106
|
+
log_info "Start executing npm install -g @openai/codex@latest"
|
|
103
107
|
if npm install -g @openai/codex@latest; then
|
|
104
108
|
now=$(date +%s)
|
|
105
109
|
printf '%s\n' "$now" > "$CODEX_STAMP_FILE"
|
|
106
|
-
log_info "npm install -g @openai/codex@latest
|
|
110
|
+
log_info "npm install -g @openai/codex@latest success"
|
|
107
111
|
else
|
|
108
112
|
local status=$?
|
|
109
113
|
log_error "npm install -g @openai/codex@latest failed (exit code ${status}); continuing startup"
|
|
@@ -114,7 +118,7 @@ ensure_codex_installed() {
|
|
|
114
118
|
ensure_codex_installed
|
|
115
119
|
|
|
116
120
|
select_python_binary() {
|
|
117
|
-
#
|
|
121
|
+
# Choose to meet CPython <=3.12 interpreter, disabled by default 3.13(pydantic-core There is no compatible wheel in the pipx base environment)
|
|
118
122
|
local allow_py313="${VIBEGO_ALLOW_PY313:-}"
|
|
119
123
|
local candidates=()
|
|
120
124
|
local chosen=""
|
|
@@ -141,7 +145,7 @@ select_python_binary() {
|
|
|
141
145
|
local major="${version_raw%%.*}"
|
|
142
146
|
local minor="${version_raw#*.}"
|
|
143
147
|
if [[ "$major" != "3" ]]; then
|
|
144
|
-
log_line "
|
|
148
|
+
log_line "jump over ${name} (Version ${version_raw}): Non-CPython 3.x" >&2
|
|
145
149
|
continue
|
|
146
150
|
fi
|
|
147
151
|
local explicit_override=0
|
|
@@ -149,113 +153,113 @@ select_python_binary() {
|
|
|
149
153
|
explicit_override=1
|
|
150
154
|
fi
|
|
151
155
|
if [[ "$minor" =~ ^[0-9]+$ ]] && (( minor == 13 )) && [[ "$allow_py313" != "1" ]] && (( explicit_override == 0 )); then
|
|
152
|
-
log_line "
|
|
156
|
+
log_line "jump over ${name} (Version ${version_raw}): Python 3 is disabled by default.13, Configurable VIBEGO_ALLOW_PY313=1 cover" >&2
|
|
153
157
|
continue
|
|
154
158
|
fi
|
|
155
159
|
if [[ "$minor" =~ ^[0-9]+$ ]] && (( minor > 13 )); then
|
|
156
|
-
log_line "
|
|
160
|
+
log_line "jump over ${name} (Version ${version_raw}): higher than 3.13" >&2
|
|
157
161
|
continue
|
|
158
162
|
fi
|
|
159
163
|
if [[ "$minor" =~ ^[0-9]+$ ]] && (( minor < 9 )); then
|
|
160
|
-
log_line "
|
|
164
|
+
log_line "jump over ${name} (Version ${version_raw}): less than 3.9, May be missing official wheels" >&2
|
|
161
165
|
continue
|
|
162
166
|
fi
|
|
163
167
|
chosen="$name"
|
|
164
|
-
log_line "
|
|
168
|
+
log_line "Using the Python interpreter:${chosen} (Version ${version_raw})" >&2
|
|
165
169
|
break
|
|
166
170
|
done
|
|
167
171
|
|
|
168
172
|
if [[ -z "$chosen" ]]; then
|
|
169
|
-
log_error "
|
|
173
|
+
log_error "no satisfaction found <=3.13 The Python interpreter can be set by VIBEGO_PYTHON Specify path"
|
|
170
174
|
exit 1
|
|
171
175
|
fi
|
|
172
176
|
|
|
173
177
|
printf '%s' "$chosen"
|
|
174
178
|
}
|
|
175
179
|
|
|
176
|
-
#
|
|
180
|
+
# Check whether Python dependencies are installed completely
|
|
177
181
|
check_deps_installed() {
|
|
178
|
-
#
|
|
179
|
-
if [[ ! -d "$
|
|
180
|
-
log_info "
|
|
182
|
+
# Check if the virtual environment exists
|
|
183
|
+
if [[ ! -d "$VENV_DIR" ]]; then
|
|
184
|
+
log_info "The virtual environment does not exist and needs to be initialized."
|
|
181
185
|
return 1
|
|
182
186
|
fi
|
|
183
187
|
|
|
184
|
-
#
|
|
185
|
-
if [[ ! -x "$
|
|
186
|
-
log_info "
|
|
188
|
+
# Check the virtual environment's Python interpreter
|
|
189
|
+
if [[ ! -x "$VENV_DIR/bin/python" ]]; then
|
|
190
|
+
log_info "Virtual environment Python interpreter missing"
|
|
187
191
|
return 1
|
|
188
192
|
fi
|
|
189
193
|
|
|
190
|
-
#
|
|
191
|
-
# aiogram: Telegram
|
|
192
|
-
# aiohttp:
|
|
193
|
-
# aiosqlite:
|
|
194
|
-
if ! "$
|
|
195
|
-
log_info "
|
|
194
|
+
# Activate the virtual environment and check key dependency packages
|
|
195
|
+
# aiogram: Telegram Botframe
|
|
196
|
+
# aiohttp: Asynchronous HTTP client
|
|
197
|
+
# aiosqlite: Asynchronous SQLite database
|
|
198
|
+
if ! "$VENV_DIR/bin/python" -c "import aiogram, aiohttp, aiosqlite" 2>/dev/null; then
|
|
199
|
+
log_info "Key dependency packages are missing or damaged"
|
|
196
200
|
return 1
|
|
197
201
|
fi
|
|
198
202
|
|
|
199
|
-
log_info "
|
|
203
|
+
log_info "The dependency check passed and the virtual environment is complete"
|
|
200
204
|
return 0
|
|
201
205
|
}
|
|
202
206
|
|
|
203
|
-
#
|
|
207
|
+
# Robust function to clean up old master processes (improved version: supports PID files + pgrep Double insurance)
|
|
204
208
|
cleanup_old_master() {
|
|
205
|
-
local max_wait=10 #
|
|
209
|
+
local max_wait=10 # Wait up to 10 seconds to exit gracefully
|
|
206
210
|
local waited=0
|
|
207
211
|
local old_pids=""
|
|
208
212
|
local master_pid_file="$STATE_DIR/master.pid"
|
|
209
213
|
|
|
210
|
-
#
|
|
214
|
+
# Option 1: Read from the PID file first
|
|
211
215
|
if [[ -f "$master_pid_file" ]]; then
|
|
212
216
|
local pid_from_file
|
|
213
217
|
pid_from_file=$(cat "$master_pid_file" 2>/dev/null || true)
|
|
214
218
|
if [[ "$pid_from_file" =~ ^[0-9]+$ ]]; then
|
|
215
219
|
if kill -0 "$pid_from_file" 2>/dev/null; then
|
|
216
220
|
old_pids="$pid_from_file"
|
|
217
|
-
log_info "
|
|
221
|
+
log_info "Old master instance detected from PID file (PID: $old_pids)"
|
|
218
222
|
else
|
|
219
|
-
log_info "PID
|
|
223
|
+
log_info "PID The file exists but the process is no longer there, clean up expired PID files"
|
|
220
224
|
rm -f "$master_pid_file"
|
|
221
225
|
fi
|
|
222
226
|
fi
|
|
223
227
|
fi
|
|
224
228
|
|
|
225
|
-
#
|
|
229
|
+
# Option 2: Use pgrep to find (supports multiple running modes)
|
|
226
230
|
if [[ -z "$old_pids" ]]; then
|
|
227
|
-
#
|
|
228
|
-
# - python.*master.py
|
|
229
|
-
# - Python.*master.py
|
|
230
|
-
# - bot.py
|
|
231
|
+
# Matching mode: supports source code running and pipx installation methods
|
|
232
|
+
# - python.*master.py(Source code running)
|
|
233
|
+
# - Python.*master.py(macOS Python on.app)
|
|
234
|
+
# - bot.py(pipx installed master alias)
|
|
231
235
|
local pgrep_pids
|
|
232
236
|
pgrep_pids=$(pgrep -f "master\.py$" 2>/dev/null || true)
|
|
233
237
|
if [[ -n "$pgrep_pids" ]]; then
|
|
234
238
|
old_pids="$pgrep_pids"
|
|
235
|
-
log_info "
|
|
239
|
+
log_info "Old master instance detected via pgrep (PID: $old_pids)"
|
|
236
240
|
fi
|
|
237
241
|
fi
|
|
238
242
|
|
|
239
|
-
#
|
|
243
|
+
# If neither method is found, it means there is no old process.
|
|
240
244
|
if [[ -z "$old_pids" ]]; then
|
|
241
|
-
log_info "
|
|
245
|
+
log_info "Old master instance not detected"
|
|
242
246
|
return 0
|
|
243
247
|
fi
|
|
244
248
|
|
|
245
|
-
#
|
|
246
|
-
log_info "
|
|
249
|
+
# Start cleaning up old processes
|
|
250
|
+
log_info "Gracefully terminating old master instance (PID: $old_pids)..."
|
|
247
251
|
|
|
248
|
-
#
|
|
252
|
+
# Send SIGTERM signal to terminate gracefully
|
|
249
253
|
for pid in $old_pids; do
|
|
250
254
|
kill -15 "$pid" 2>/dev/null || true
|
|
251
255
|
done
|
|
252
256
|
|
|
253
|
-
#
|
|
257
|
+
# Loop waiting for process to exit
|
|
254
258
|
while (( waited < max_wait )); do
|
|
255
259
|
sleep 1
|
|
256
260
|
((waited++))
|
|
257
261
|
|
|
258
|
-
#
|
|
262
|
+
# Check if all PIDs have exited
|
|
259
263
|
local all_exited=1
|
|
260
264
|
for pid in $old_pids; do
|
|
261
265
|
if kill -0 "$pid" 2>/dev/null; then
|
|
@@ -265,20 +269,20 @@ cleanup_old_master() {
|
|
|
265
269
|
done
|
|
266
270
|
|
|
267
271
|
if (( all_exited )); then
|
|
268
|
-
log_info "
|
|
272
|
+
log_info "OK: The old master exited gracefully (elapsed ${waited}s)"
|
|
269
273
|
rm -f "$master_pid_file"
|
|
270
274
|
return 0
|
|
271
275
|
fi
|
|
272
276
|
done
|
|
273
277
|
|
|
274
|
-
#
|
|
275
|
-
log_info "
|
|
278
|
+
# Graceful termination timeout, execution forced end
|
|
279
|
+
log_info "graceful termination timeout (${max_wait}Second), Execute forced end..."
|
|
276
280
|
for pid in $old_pids; do
|
|
277
281
|
kill -9 "$pid" 2>/dev/null || true
|
|
278
282
|
done
|
|
279
283
|
sleep 2
|
|
280
284
|
|
|
281
|
-
#
|
|
285
|
+
# final check
|
|
282
286
|
local remaining_pids=""
|
|
283
287
|
for pid in $old_pids; do
|
|
284
288
|
if kill -0 "$pid" 2>/dev/null; then
|
|
@@ -287,75 +291,91 @@ cleanup_old_master() {
|
|
|
287
291
|
done
|
|
288
292
|
|
|
289
293
|
if [[ -n "$remaining_pids" ]]; then
|
|
290
|
-
log_error "
|
|
291
|
-
log_error "
|
|
294
|
+
log_error "ERROR: Unable to clean up old master process (residual PID:$remaining_pids)"
|
|
295
|
+
log_error "Please execute manually: kill -9$remaining_pids"
|
|
292
296
|
exit 1
|
|
293
297
|
fi
|
|
294
298
|
|
|
295
|
-
log_info "
|
|
299
|
+
log_info "OK: The old master instance has been forcefully cleaned"
|
|
296
300
|
rm -f "$master_pid_file"
|
|
297
301
|
return 0
|
|
298
302
|
}
|
|
299
303
|
|
|
300
|
-
#
|
|
304
|
+
# Call the cleanup function
|
|
301
305
|
cleanup_old_master
|
|
302
306
|
|
|
303
|
-
#
|
|
307
|
+
# Smart dependency management: install only when necessary
|
|
304
308
|
REQUIREMENTS_FILE="${VIBEGO_REQUIREMENTS_PATH:-$ROOT_DIR/scripts/requirements.txt}"
|
|
305
309
|
if [[ ! -f "$REQUIREMENTS_FILE" ]]; then
|
|
306
|
-
log_error "
|
|
310
|
+
log_error "Dependency files are missing: $REQUIREMENTS_FILE"
|
|
307
311
|
exit 1
|
|
308
312
|
fi
|
|
309
313
|
|
|
310
314
|
PYTHON_BIN="$(select_python_binary)"
|
|
311
315
|
|
|
312
|
-
#
|
|
316
|
+
# Compatible with oldVersion: If it is detected in the warehouse .venv, then migrate to the runtime directory
|
|
317
|
+
migrate_legacy_venv() {
|
|
318
|
+
if [[ -d "$LEGACY_VENV_DIR" && ! -e "$VENV_DIR" ]]; then
|
|
319
|
+
log_info "Old virtual environment directory detected:$LEGACY_VENV_DIR, Prepare to migrate to $VENV_DIR"
|
|
320
|
+
if mv "$LEGACY_VENV_DIR" "$VENV_DIR"; then
|
|
321
|
+
log_info "The virtual environment has been migrated to:$VENV_DIR"
|
|
322
|
+
else
|
|
323
|
+
log_error "Migration of the old virtual environment failed. Please check manually and try again."
|
|
324
|
+
fi
|
|
325
|
+
fi
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
migrate_legacy_venv
|
|
329
|
+
|
|
330
|
+
# Check if dependencies need to be installed
|
|
313
331
|
if check_deps_installed; then
|
|
314
|
-
log_info "
|
|
315
|
-
|
|
332
|
+
log_info "Dependencies are installed and complete, jump overpip install(accelerated restart)"
|
|
333
|
+
# shellcheck disable=SC1091
|
|
334
|
+
source "$VENV_DIR/bin/activate"
|
|
316
335
|
else
|
|
317
|
-
log_info "
|
|
336
|
+
log_info "First startup or missing dependencies, installing dependencies..."
|
|
318
337
|
|
|
319
|
-
#
|
|
320
|
-
"$PYTHON_BIN" -m venv
|
|
321
|
-
|
|
338
|
+
# Create or rebuild a virtual environment
|
|
339
|
+
"$PYTHON_BIN" -m venv "$VENV_DIR"
|
|
340
|
+
# shellcheck disable=SC1091
|
|
341
|
+
source "$VENV_DIR/bin/activate"
|
|
322
342
|
|
|
323
|
-
#
|
|
324
|
-
#
|
|
325
|
-
log_info "
|
|
343
|
+
# Install dependencies
|
|
344
|
+
# Redirect pip output to log file to avoid BrokenPipe errors
|
|
345
|
+
log_info "Start executing pip install -r $REQUIREMENTS_FILE"
|
|
326
346
|
PIP_LOG_FILE="$LOG_DIR/pip_install_$(date +%Y%m%d_%H%M%S).log"
|
|
327
347
|
if pip install -r "$REQUIREMENTS_FILE" > "$PIP_LOG_FILE" 2>&1; then
|
|
328
|
-
log_info "
|
|
348
|
+
log_info "Dependency installation completed"
|
|
329
349
|
else
|
|
330
350
|
PIP_EXIT_CODE=$?
|
|
331
|
-
log_error "pip install
|
|
332
|
-
#
|
|
351
|
+
log_error "pip install Failure, exit code=$PIP_EXIT_CODE, See details $PIP_LOG_FILE"
|
|
352
|
+
# If it is BrokenPipe (Exit code 141), Verify that dependencies are actually installed
|
|
333
353
|
if [[ $PIP_EXIT_CODE -eq 141 ]]; then
|
|
334
|
-
log_info "
|
|
335
|
-
#
|
|
336
|
-
if "$
|
|
337
|
-
log_info "
|
|
354
|
+
log_info "BrokenPipe error detected, dependency integrity verified..."
|
|
355
|
+
# Verify whether key dependency packages can be imported
|
|
356
|
+
if "$VENV_DIR/bin/python" -c "import aiogram, aiohttp, aiosqlite" 2>/dev/null; then
|
|
357
|
+
log_info "Dependency verification passed, BrokenPipe can be ignored and execution continues."
|
|
338
358
|
else
|
|
339
|
-
log_error "
|
|
359
|
+
log_error "Dependency verification failed. Although it is BrokenPipe, the dependency is not completely installed."
|
|
340
360
|
exit 1
|
|
341
361
|
fi
|
|
342
362
|
else
|
|
343
|
-
#
|
|
363
|
+
# If there are other errors, exit directly.
|
|
344
364
|
exit $PIP_EXIT_CODE
|
|
345
365
|
fi
|
|
346
366
|
fi
|
|
347
367
|
fi
|
|
348
368
|
|
|
349
|
-
#
|
|
350
|
-
#
|
|
369
|
+
# Start the master in the background, and the log falls in vibe.log
|
|
370
|
+
# Explicitly pass the restart flag environment variable if present
|
|
351
371
|
if [[ -n "${MASTER_RESTART_EXPECTED:-}" ]]; then
|
|
352
|
-
log_info "
|
|
372
|
+
log_info "Restart flag environment variable MASTER detected_RESTART_EXPECTED=$MASTER_RESTART_EXPECTED"
|
|
353
373
|
export MASTER_RESTART_EXPECTED
|
|
354
374
|
fi
|
|
355
375
|
|
|
356
|
-
log_info "
|
|
376
|
+
log_info "Prepare to start the master process..."
|
|
357
377
|
|
|
358
|
-
#
|
|
378
|
+
# Clean old error logs (keep the last 10)
|
|
359
379
|
cleanup_old_error_logs() {
|
|
360
380
|
local error_log_pattern="$LOG_DIR/master_error_*.log"
|
|
361
381
|
local error_logs
|
|
@@ -366,7 +386,7 @@ cleanup_old_error_logs() {
|
|
|
366
386
|
((count++))
|
|
367
387
|
if (( count > 10 )); then
|
|
368
388
|
rm -f "$logfile"
|
|
369
|
-
log_info "
|
|
389
|
+
log_info "Cleaned old error logs: $logfile"
|
|
370
390
|
fi
|
|
371
391
|
done <<< "$error_logs"
|
|
372
392
|
fi
|
|
@@ -374,73 +394,73 @@ cleanup_old_error_logs() {
|
|
|
374
394
|
|
|
375
395
|
cleanup_old_error_logs
|
|
376
396
|
|
|
377
|
-
#
|
|
397
|
+
# Create a timestamped error log file
|
|
378
398
|
MASTER_ERROR_LOG="$LOG_DIR/master_error_$(date +%Y%m%d_%H%M%S).log"
|
|
379
399
|
MASTER_STDOUT_LOG="$LOG_DIR/master_stdout.log"
|
|
380
400
|
|
|
381
|
-
#
|
|
382
|
-
#
|
|
383
|
-
#
|
|
384
|
-
MASTER_RESTART_SIGNAL_PATH="$MASTER_RESTART_SIGNAL_PATH" nohup "$
|
|
401
|
+
# Explicitly pass environment variables to the nohup process to ensure that the restart signal file path is correct
|
|
402
|
+
# Using virtual environment Python interpreter, avoidVersionMismatch causes dependency loading to fail
|
|
403
|
+
# Important: Save stderr to a log file to facilitate troubleshooting startup failures.
|
|
404
|
+
MASTER_RESTART_SIGNAL_PATH="$MASTER_RESTART_SIGNAL_PATH" nohup "$VENV_DIR/bin/python" master.py > "$MASTER_STDOUT_LOG" 2> "$MASTER_ERROR_LOG" &
|
|
385
405
|
MASTER_PID=$!
|
|
386
406
|
|
|
387
|
-
#
|
|
407
|
+
# Robustness check: ensure processsuccessstart up
|
|
388
408
|
if [[ -z "${MASTER_PID:-}" ]]; then
|
|
389
|
-
log_error "
|
|
390
|
-
log_error "
|
|
409
|
+
log_error "ERROR: Unable to obtain master process PID; startup failed"
|
|
410
|
+
log_error "Possible reasons: python command is not available or master.py There are grammatical errors"
|
|
391
411
|
exit 1
|
|
392
412
|
fi
|
|
393
413
|
|
|
394
|
-
#
|
|
414
|
+
# Check if the process is still running after a short wait
|
|
395
415
|
sleep 0.5
|
|
396
416
|
if ! kill -0 "$MASTER_PID" 2>/dev/null; then
|
|
397
|
-
log_error "
|
|
398
|
-
log_error "
|
|
399
|
-
log_error " - master.py
|
|
400
|
-
log_error " -
|
|
401
|
-
log_error " -
|
|
417
|
+
log_error "ERROR: Master process exited immediately after starting (PID=$MASTER_PID)"
|
|
418
|
+
log_error "Check, please:"
|
|
419
|
+
log_error " - master.py whetherThere are grammatical errors: python master.py"
|
|
420
|
+
log_error " - Are dependencies complete?: pip list | grep aiogram"
|
|
421
|
+
log_error " - error log: $MASTER_ERROR_LOG"
|
|
402
422
|
|
|
403
|
-
#
|
|
423
|
+
# outputerror logthe end 20 OK, Help locate problems quickly
|
|
404
424
|
if [[ -s "$MASTER_ERROR_LOG" ]]; then
|
|
405
425
|
log_error ""
|
|
406
|
-
log_error "===
|
|
426
|
+
log_error "=== error logat last 20 OK ==="
|
|
407
427
|
tail -20 "$MASTER_ERROR_LOG" | while IFS= read -r line; do
|
|
408
428
|
log_error " $line"
|
|
409
429
|
done
|
|
410
430
|
log_error "=========================="
|
|
411
431
|
else
|
|
412
|
-
log_error "
|
|
432
|
+
log_error "error logFile is empty, It may be an environment variable or path problem"
|
|
413
433
|
fi
|
|
414
434
|
|
|
415
435
|
exit 1
|
|
416
436
|
fi
|
|
417
437
|
|
|
418
|
-
log_info "master
|
|
438
|
+
log_info "master Started in background, PID=$MASTER_PID, Log writing ${LOG_FILE}"
|
|
419
439
|
|
|
420
|
-
#
|
|
421
|
-
log_info "
|
|
440
|
+
# Health check: wait for master to come online and verify key workers
|
|
441
|
+
log_info "Start health check..."
|
|
422
442
|
HEALTHCHECK_START=$(date +%s)
|
|
423
443
|
|
|
424
444
|
if python scripts/master_healthcheck.py --project hyphavibebotbackend; then
|
|
425
445
|
HEALTHCHECK_END=$(date +%s)
|
|
426
446
|
HEALTHCHECK_DURATION=$((HEALTHCHECK_END - HEALTHCHECK_START))
|
|
427
|
-
log_info "
|
|
447
|
+
log_info "OK: Master health check passed (elapsed ${HEALTHCHECK_DURATION}s)"
|
|
428
448
|
else
|
|
429
449
|
HEALTHCHECK_END=$(date +%s)
|
|
430
450
|
HEALTHCHECK_DURATION=$((HEALTHCHECK_END - HEALTHCHECK_START))
|
|
431
|
-
log_error "⚠️ master
|
|
432
|
-
log_error "
|
|
433
|
-
log_error " -
|
|
434
|
-
log_error " -
|
|
435
|
-
log_error " -
|
|
436
|
-
log_error " -
|
|
437
|
-
|
|
438
|
-
#
|
|
451
|
+
log_error "⚠️ master Health check failed, time consuming ${HEALTHCHECK_DURATION}s"
|
|
452
|
+
log_error "It is recommended to check:"
|
|
453
|
+
log_error " - process status: ps aux | grep 'python.*master.py'"
|
|
454
|
+
log_error " - Startup log: tail -100 $LOG_DIR/start.log"
|
|
455
|
+
log_error " - Run log: tail -100 $LOG_FILE"
|
|
456
|
+
log_error " - Process PID: $MASTER_PID"
|
|
457
|
+
|
|
458
|
+
# Check if the process is still running
|
|
439
459
|
if kill -0 "$MASTER_PID" 2>/dev/null; then
|
|
440
|
-
log_info "master
|
|
441
|
-
log_info "⚠️
|
|
460
|
+
log_info "master The process is still running (PID=$MASTER_PID), Allow startup to continue"
|
|
461
|
+
log_info "⚠️ Please manually verify that the service is working properly"
|
|
442
462
|
else
|
|
443
|
-
log_error "
|
|
463
|
+
log_error "ERROR: Master process exited and failed to start"
|
|
444
464
|
exit 1
|
|
445
465
|
fi
|
|
446
466
|
fi
|
scripts/start_tmux_codex.sh
CHANGED
|
@@ -19,7 +19,7 @@ MODEL_SESSION_ROOT="${MODEL_SESSION_ROOT:-${CODEX_SESSION_ROOT:-$HOME/.codex/ses
|
|
|
19
19
|
MODEL_SESSION_GLOB="${MODEL_SESSION_GLOB:-rollout-*.jsonl}"
|
|
20
20
|
SESSION_POINTER_FILE="${SESSION_POINTER_FILE:-$LOG_ROOT/${MODEL_NAME:-codex}/${PROJECT_NAME:-project}/current_session.txt}"
|
|
21
21
|
|
|
22
|
-
#
|
|
22
|
+
# Avoid oh-my-zsh popping up update prompts in non-interactive environments
|
|
23
23
|
export DISABLE_UPDATE_PROMPT="${DISABLE_UPDATE_PROMPT:-true}"
|
|
24
24
|
|
|
25
25
|
expand_path() {
|
|
@@ -40,7 +40,7 @@ KILL_SESSION=0
|
|
|
40
40
|
|
|
41
41
|
usage() {
|
|
42
42
|
cat <<USAGE
|
|
43
|
-
|
|
43
|
+
usage:${0##*/} [--dry-run] [--force] [--restart] [--kill]
|
|
44
44
|
USAGE
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -51,13 +51,13 @@ while [[ $# -gt 0 ]]; do
|
|
|
51
51
|
--restart) RESTART=1; FORCE_START=1 ;;
|
|
52
52
|
--kill) KILL_SESSION=1 ;;
|
|
53
53
|
-h|--help) usage; exit 0 ;;
|
|
54
|
-
*) echo "
|
|
54
|
+
*) echo "unknown parameters: $1" >&2; usage; exit 1 ;;
|
|
55
55
|
esac
|
|
56
56
|
shift
|
|
57
57
|
done
|
|
58
58
|
|
|
59
59
|
if ! command -v tmux >/dev/null 2>&1; then
|
|
60
|
-
echo "tmux
|
|
60
|
+
echo "tmux Not installed" >&2
|
|
61
61
|
exit 1
|
|
62
62
|
fi
|
|
63
63
|
|
|
@@ -98,12 +98,12 @@ else
|
|
|
98
98
|
fi
|
|
99
99
|
fi
|
|
100
100
|
|
|
101
|
-
#
|
|
101
|
+
# Clean up before starting to avoid old logs exceeding the limit.
|
|
102
102
|
if ! env \
|
|
103
103
|
MODEL_LOG_MAX_BYTES="$MODEL_LOG_MAX_BYTES" \
|
|
104
104
|
MODEL_LOG_RETENTION_SECONDS="$MODEL_LOG_RETENTION_SECONDS" \
|
|
105
105
|
"$PYTHON_EXEC" "$LOG_WRITER" "$LOG_PATH" </dev/null; then
|
|
106
|
-
echo "
|
|
106
|
+
echo "Preprocessing log file failed" >&2
|
|
107
107
|
exit 1
|
|
108
108
|
fi
|
|
109
109
|
|
|
@@ -115,7 +115,7 @@ printf -v PIPE_CMD 'env MODEL_LOG_MAX_BYTES=%q MODEL_LOG_RETENTION_SECONDS=%q %q
|
|
|
115
115
|
"$LOG_PATH"
|
|
116
116
|
run_tmux pipe-pane -o -t "$SESSION_NAME" "$PIPE_CMD"
|
|
117
117
|
|
|
118
|
-
#
|
|
118
|
+
# Synchronize environment variables to the tmux server to avoid losing settings when reusing old sessions
|
|
119
119
|
run_tmux set-environment -t "$SESSION_NAME" DISABLE_UPDATE_PROMPT "${DISABLE_UPDATE_PROMPT:-true}"
|
|
120
120
|
if [[ -n "${CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING:-}" ]]; then
|
|
121
121
|
run_tmux set-environment -t "$SESSION_NAME" CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING "${CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING}"
|
|
@@ -138,7 +138,7 @@ fi
|
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
if (( DRY_RUN )); then
|
|
141
|
-
printf '[dry-run]
|
|
141
|
+
printf '[dry-run] Session log path: %s\n' "$SESSION_POINTER_FILE"
|
|
142
142
|
exit 0
|
|
143
143
|
fi
|
|
144
144
|
|