SIGN IN SIGN UP

feat: weight-sync coordination, reusable route bundle, session-id program fallback

Three additions to make ThunderAgent embeddable from external FastAPI apps
(e.g. an RL training framework that wraps the router with its own
integration layer) without forking the package.

1. Weight-sync coordination on MultiBackendRouter
   - begin_weight_sync / end_weight_sync / weight_sync_active
   - update_program_before_request blocks on _weight_sync_event so new
     data-plane requests pause while a trainer is broadcasting weights
   - Scheduler loop skips ticks while weight sync is active
   - Watchdog auto-exits after configurable timeout (default 300s)
   - Two HTTP routes /weight_sync/begin and /weight_sync/end

2. register_routes(app, ta_router, config=None) in app.py
   - Extracts all HTTP route registration into a reusable function so
     external FastAPI apps can mount the same route bundle on their own
     router/lifespan, with their own config.
   - Standalone python -m ThunderAgent entry is preserved: the bottom of
     app.py still constructs `router = _create_router()` / `app = FastAPI(...)`
     and calls register_routes(app, router).

3. get_program_id(payload, headers=None)
   - Adds an X-Session-ID header fallback after the payload checks, so
     clients that already route by session id can reuse it as the
     ThunderAgent program id without injecting program_id into the payload.

No behavior change for the standalone server. Library users can now:

    from ThunderAgent import MultiBackendRouter, register_routes
    router = MultiBackendRouter(...)
    register_routes(my_fastapi_app, router)
E
ergt10 committed
233b63fcb6a24f1c332105b042f4c8aaca099861
Parent: aebad64