4 Commits

Author SHA1 Message Date
teernisse
a7b2b3b902 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>
2026-02-25 15:01:26 -05:00
teernisse
e994c7a0e8 feat(server): rewrite Codex pane discovery using process inspection
Replace the zellij dump-layout approach with direct process inspection
for matching Codex sessions to Zellij panes. The old method couldn't
extract pane IDs from layout output, leaving them empty. The new
approach uses a three-step pipeline:

1. pgrep -x codex to find running Codex PIDs
2. ps eww to extract ZELLIJ_PANE_ID and ZELLIJ_SESSION_NAME from each
   process's inherited environment variables
3. lsof -a -p <pids> -d cwd to batch-resolve working directories

Session-to-pane matching then uses a two-tier strategy:
- Primary: lsof -t <session_file> to find which PID has the JSONL open
- Fallback: normalized CWD comparison

Also adds:
- _codex_pane_cache with 5-second TTL to avoid running pgrep/ps/lsof
  on every dashboard poll cycle
- _dismissed_codex_ids set to track Codex sessions the user has
  dismissed, preventing re-discovery on subsequent polls
- Clearer error message when session lacks pane info for input routing
2026-02-25 11:51:28 -05:00
teernisse
a9ed8f90f4 feat(server): add Codex session support and improve session lifecycle
Extend AMC to monitor Codex sessions alongside Claude Code:

Codex Integration:
- Discover active Codex sessions from ~/.codex/sessions/*.jsonl
- Parse Codex JSONL format (response_item/message payloads) for
  conversation history, filtering out developer role injections
- Extract session metadata (cwd, timestamp) from session_meta records
- Match Codex sessions to Zellij panes via cwd for response injection
- Add ?agent=codex query param to /api/conversation endpoint

Session Lifecycle Improvements:
- Cache Zellij session list for 5 seconds to reduce subprocess calls
- Proactive liveness check: auto-delete orphan "starting" sessions
  when their Zellij session no longer exists
- Clean up stale "starting" sessions after 1 hour (likely orphaned)
- Preserve existing event log cleanup (24h for orphan logs)

Code Quality:
- Refactor _serve_conversation into _parse_claude_conversation and
  _parse_codex_conversation for cleaner separation
- Add _discover_active_codex_sessions for session file generation
- Add _get_codex_zellij_panes to match sessions to panes
- Use JSON error responses consistently via _json_error helper
2026-02-25 11:21:30 -05:00
teernisse
b2a5712202 Initial work, pre-preact refactor 2026-02-25 09:21:59 -05:00