feat(server): container/devcontainer support lifecycle #1121

Open
freemo wants to merge 4 commits from feature/m9-container-lifecycle into master

4 Commits

Author SHA1 Message Date
brent.edwards f7e9549779 fix(server): correct A2aRequest.method usage and A2A test payloads
CI / load-versions (pull_request) Successful in 18s
CI / push-validation (pull_request) Successful in 26s
CI / build (pull_request) Successful in 47s
CI / lint (pull_request) Failing after 1m0s
CI / quality (pull_request) Successful in 1m3s
CI / typecheck (pull_request) Successful in 1m12s
CI / security (pull_request) Successful in 1m19s
CI / helm (pull_request) Successful in 44s
CI / unit_tests (pull_request) Failing after 2m51s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / integration_tests (pull_request) Failing after 10m52s
CI / status-check (pull_request) Failing after 4s
Add more feature tests.

Issues closed: #865
2026-06-18 03:09:04 -04:00
HAL9000 8bcc957e99 fix(server): correct A2aRequest.method usage and A2A test payloads
asgi_app.py logged a2a_request.operation (no such attribute on
A2aRequest) instead of a2a_request.method — Pyright error.

Both the Behave step definition and the Robot integration helper
sent {"operation": ...} in the JSON body, but A2aRequest requires
{"method": ...} per JSON-RPC 2.0, causing validation to return 400.

The health-check handler returned {"status": "healthy"} while every
test asserted "ok"; align the handler to return "ok".

The A2A response status assertion checked data.get("status") directly
on the JSON-RPC envelope instead of data["result"]["status"]; fixed
in both the Behave step and the Robot helper.
2026-06-18 03:09:04 -04:00
freemo 41cf1221b3 feat(server): container/devcontainer support lifecycle
Implement server-side container and devcontainer lifecycle management
for the CleverAgents server infrastructure.

New modules in src/cleveragents/infrastructure/server/containers/:
- DevcontainerSpec: Pydantic model for devcontainer.json parsing and
  validation (image, build, features, mounts, env vars, ports,
  hostRequirements, postCreateCommand, remoteUser, workspaceFolder).
- ResourceLimits: CPU, memory, storage, and PID limits model with
  Docker CLI argument generation and hostRequirements conversion.
- ContainerManager: Server-side lifecycle orchestration with
  create/start/stop/destroy operations using pluggable Docker CLI
  runner (mocked for tests).
- HealthMonitor: Periodic container health probing via docker
  inspect with background thread management and probe history.
- ContainerStatus enum: pending/created/running/stopped/destroyed/error
  with validated state transitions.

Tests:
- Behave BDD: 67 scenarios covering spec parsing, resource limits,
  lifecycle operations, health monitoring, and error handling
  (features/container_lifecycle.feature).
- Robot Framework: 13 integration test cases with mock Docker
  runner (robot/container_lifecycle_server.robot).

ISSUES CLOSED: #865
2026-06-18 03:08:37 -04:00
freemo 638d03b2b0 feat(server): ASGI endpoint via uvicorn
Implement FastAPI-based ASGI application served by uvicorn for
the CleverAgents server mode. Add health check endpoint, A2A
JSON-RPC routing, configurable host:port binding, and graceful
shutdown handling. Server launches via `agents server start`.

- Add FastAPI ASGI app factory at infrastructure/server/asgi_app.py
  with /.well-known/agent.json (Agent Card), /health (liveness),
  and /a2a (A2A JSON-RPC 2.0 dispatch via A2aLocalFacade)
- Add ServerLifecycle class at infrastructure/server/server_lifecycle.py
  wrapping uvicorn.Server with SIGTERM/SIGINT graceful shutdown
- Add `agents server start` CLI command with --host, --port, --log-level
  options, resolving defaults from Settings
- Add fastapi>=0.115.0 dependency to pyproject.toml (uvicorn already present)
- Add Behave BDD tests (features/server_lifecycle.feature, 20 scenarios)
- Add Robot Framework integration tests (robot/server_lifecycle.robot)
- Update CHANGELOG.md and vulture_whitelist.py

ISSUES CLOSED: #862
2026-06-18 03:01:43 -04:00