refactor(server): extract amc_server package from monolithic script
Split the 860+ line bin/amc-server into a modular Python package:
amc_server/
__init__.py - Package marker
context.py - Shared constants (DATA_DIR, PORT, CLAUDE_PROJECTS_DIR, etc.)
handler.py - AMCHandler class using mixin composition
logging_utils.py - Structured logging setup with signal handlers
server.py - Main entry point (ThreadingHTTPServer)
mixins/
__init__.py - Mixin package marker
control.py - Session control (dismiss, respond via Zellij)
conversation.py - Conversation history parsing (Claude JSONL format)
discovery.py - Session discovery (Codex pane inspection, Zellij cache)
http.py - HTTP response helpers (CORS, JSON, static files)
parsing.py - Session state parsing and aggregation
state.py - Session state endpoint logic
The monolithic bin/amc-server becomes a thin launcher that just imports
and calls main(). This separation enables:
- Easier testing of individual components
- Better IDE support (proper Python package structure)
- Cleaner separation of concerns (discovery vs parsing vs control)
- ThreadingHTTPServer instead of single-threaded (handles concurrent requests)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
31
amc_server/logging_utils.py
Normal file
31
amc_server/logging_utils.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
|
||||
LOGGER = logging.getLogger("amc.server")
|
||||
|
||||
|
||||
def configure_logging():
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s %(levelname)s %(message)s",
|
||||
stream=sys.stdout,
|
||||
force=True,
|
||||
)
|
||||
|
||||
|
||||
def install_signal_handlers(server):
|
||||
"""Log termination signals and shut down cleanly."""
|
||||
|
||||
def _handle(signum, _frame):
|
||||
LOGGER.warning("Received signal %s, shutting down AMC server", signum)
|
||||
# shutdown() blocks until serve_forever loop wakes; call from a helper thread.
|
||||
threading.Thread(target=server.shutdown, daemon=True).start()
|
||||
|
||||
for sig in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP):
|
||||
try:
|
||||
signal.signal(sig, _handle)
|
||||
except (ValueError, OSError, RuntimeError):
|
||||
# Some environments may restrict signal registration.
|
||||
continue
|
||||
Reference in New Issue
Block a user