fix: wire auto_install_agent_deps into server.py startup (#216)
* fix: wire auto_install_agent_deps into server.py startup; add api/startup.py to ARCHITECTURE.md * fix(tests): kill stale process on test port before server start in conftest Stale servers left by QA harness runs (ports 8792/8793 etc.) or prior test sessions could interfere with conftest starting its own server on TEST_PORT (8788). If the port was already occupied, _wait_for_server hit the wrong server and tests got unexpected 404s/500s, failing non-deterministically — the 'conftest isolation issue' seen this session. Fix: run fuser -k on TEST_PORT before launching the new server process, with a 0.5s sleep for port release. The full suite now runs 571/571 reliably regardless of what other servers were previously active. --------- Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
This commit is contained in:
@@ -40,6 +40,7 @@ This makes the code easy to modify from a terminal or by an agent.
|
|||||||
models.py Session model + CRUD, per-session profile tracking (~137 lines)
|
models.py Session model + CRUD, per-session profile tracking (~137 lines)
|
||||||
profiles.py Profile state management, hermes_cli wrapper (~246 lines)
|
profiles.py Profile state management, hermes_cli wrapper (~246 lines)
|
||||||
routes.py All GET + POST route handlers (~1180 lines)
|
routes.py All GET + POST route handlers (~1180 lines)
|
||||||
|
startup.py Startup helpers: auto_install_agent_deps() (~50 lines)
|
||||||
streaming.py SSE engine, run_agent, cancel, HERMES_HOME save/restore (~236 lines)
|
streaming.py SSE engine, run_agent, cancel, HERMES_HOME save/restore (~236 lines)
|
||||||
upload.py Multipart parser, file upload handler (~78 lines)
|
upload.py Multipart parser, file upload handler (~78 lines)
|
||||||
workspace.py File ops: list_dir, read_file_content, workspace helpers (~77 lines)
|
workspace.py File ops: list_dir, read_file_content, workspace helpers (~77 lines)
|
||||||
|
|||||||
12
server.py
12
server.py
@@ -12,6 +12,7 @@ from api.auth import check_auth
|
|||||||
from api.config import HOST, PORT, STATE_DIR, SESSION_DIR, DEFAULT_WORKSPACE
|
from api.config import HOST, PORT, STATE_DIR, SESSION_DIR, DEFAULT_WORKSPACE
|
||||||
from api.helpers import j
|
from api.helpers import j
|
||||||
from api.routes import handle_get, handle_post
|
from api.routes import handle_get, handle_post
|
||||||
|
from api.startup import auto_install_agent_deps
|
||||||
|
|
||||||
|
|
||||||
class Handler(BaseHTTPRequestHandler):
|
class Handler(BaseHTTPRequestHandler):
|
||||||
@@ -75,7 +76,16 @@ def main() -> None:
|
|||||||
print(f'[!!] Warning: Hermes agent found but missing modules: {missing}', flush=True)
|
print(f'[!!] Warning: Hermes agent found but missing modules: {missing}', flush=True)
|
||||||
for mod, err in errors.items():
|
for mod, err in errors.items():
|
||||||
print(f' {mod}: {err}', flush=True)
|
print(f' {mod}: {err}', flush=True)
|
||||||
print(' Agent features may not work correctly.', flush=True)
|
print(' Attempting to install missing dependencies from agent requirements.txt...', flush=True)
|
||||||
|
auto_install_agent_deps()
|
||||||
|
ok, missing, errors = verify_hermes_imports()
|
||||||
|
if not ok:
|
||||||
|
print(f'[!!] Still missing after install attempt: {missing}', flush=True)
|
||||||
|
for mod, err in errors.items():
|
||||||
|
print(f' {mod}: {err}', flush=True)
|
||||||
|
print(' Agent features may not work correctly.', flush=True)
|
||||||
|
else:
|
||||||
|
print('[ok] Agent dependencies installed successfully.', flush=True)
|
||||||
|
|
||||||
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
SESSION_DIR.mkdir(parents=True, exist_ok=True)
|
SESSION_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
@@ -210,6 +210,18 @@ def test_server():
|
|||||||
Start an isolated test server on TEST_PORT with a clean state directory.
|
Start an isolated test server on TEST_PORT with a clean state directory.
|
||||||
Paths are discovered dynamically -- no hardcoded absolute path assumptions.
|
Paths are discovered dynamically -- no hardcoded absolute path assumptions.
|
||||||
"""
|
"""
|
||||||
|
# Kill any leftover process on the test port before starting.
|
||||||
|
# Stale servers from QA harness runs or prior test sessions cause
|
||||||
|
# conftest to think the server is already up, producing false failures.
|
||||||
|
try:
|
||||||
|
import subprocess as _sp
|
||||||
|
_sp.run(['fuser', '-k', f'{TEST_PORT}/tcp'],
|
||||||
|
capture_output=True, timeout=5)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
import time as _time
|
||||||
|
_time.sleep(0.5) # brief pause to let the port release
|
||||||
|
|
||||||
# Clean slate
|
# Clean slate
|
||||||
if TEST_STATE_DIR.exists():
|
if TEST_STATE_DIR.exists():
|
||||||
shutil.rmtree(TEST_STATE_DIR)
|
shutil.rmtree(TEST_STATE_DIR)
|
||||||
|
|||||||
Reference in New Issue
Block a user