Skip to content

routes

routes

Route handlers for the OpenAI-compatible API server.

Classes

Functions

chat_completions async

chat_completions(request_body: ChatCompletionRequest, request: Request)

Handle chat completion requests (streaming and non-streaming).

Source code in src/openjarvis/server/routes.py
@router.post("/v1/chat/completions")
async def chat_completions(request_body: ChatCompletionRequest, request: Request):
    """Handle chat completion requests (streaming and non-streaming)."""
    engine = request.app.state.engine
    agent = getattr(request.app.state, "agent", None)
    model = request_body.model

    if request_body.stream:
        bus = getattr(request.app.state, "bus", None)
        if agent is not None and bus is not None:
            return await _handle_agent_stream(agent, bus, model, request_body)
        return await _handle_stream(engine, model, request_body)

    # Non-streaming: use agent if available, otherwise direct engine call
    if agent is not None:
        return _handle_agent(agent, model, request_body)

    bus = getattr(request.app.state, "bus", None)
    return _handle_direct(engine, model, request_body, bus=bus)

list_models async

list_models(request: Request) -> ModelListResponse

List available models from the engine.

Source code in src/openjarvis/server/routes.py
@router.get("/v1/models")
async def list_models(request: Request) -> ModelListResponse:
    """List available models from the engine."""
    engine = request.app.state.engine
    model_ids = engine.list_models()
    return ModelListResponse(
        data=[ModelObject(id=mid) for mid in model_ids],
    )

savings async

savings(request: Request)

Return savings summary compared to cloud providers.

Only includes telemetry from the current server session so that counters start at zero each time a new model + agent is launched.

Source code in src/openjarvis/server/routes.py
@router.get("/v1/savings")
async def savings(request: Request):
    """Return savings summary compared to cloud providers.

    Only includes telemetry from the current server session so that
    counters start at zero each time a new model + agent is launched.
    """
    from openjarvis.core.config import DEFAULT_CONFIG_DIR
    from openjarvis.server.savings import compute_savings, savings_to_dict
    from openjarvis.telemetry.aggregator import TelemetryAggregator

    db_path = DEFAULT_CONFIG_DIR / "telemetry.db"
    if not db_path.exists():
        empty = compute_savings(0, 0, 0)
        return savings_to_dict(empty)

    session_start = getattr(request.app.state, "session_start", None)

    agg = TelemetryAggregator(db_path)
    try:
        summary = agg.summary(since=session_start)
        result = compute_savings(
            prompt_tokens=sum(m.prompt_tokens for m in summary.per_model),
            completion_tokens=sum(m.completion_tokens for m in summary.per_model),
            total_calls=summary.total_calls,
            session_start=session_start if session_start else 0.0,
        )
        return savings_to_dict(result)
    finally:
        agg.close()

server_info async

server_info(request: Request)

Return server configuration: model, agent, engine.

Source code in src/openjarvis/server/routes.py
@router.get("/v1/info")
async def server_info(request: Request):
    """Return server configuration: model, agent, engine."""
    agent = getattr(request.app.state, "agent", None)
    agent_id = getattr(agent, "agent_id", None) if agent else None
    # Fall back to configured agent name if agent didn't instantiate
    if agent_id is None:
        agent_id = getattr(request.app.state, "agent_name", None)
    return {
        "model": getattr(request.app.state, "model", ""),
        "agent": agent_id,
        "engine": getattr(request.app.state, "engine_name", ""),
    }

health async

health(request: Request)

Health check endpoint.

Source code in src/openjarvis/server/routes.py
@router.get("/health")
async def health(request: Request):
    """Health check endpoint."""
    engine = request.app.state.engine
    healthy = engine.health()
    if not healthy:
        raise HTTPException(status_code=503, detail="Engine unhealthy")
    return {"status": "ok"}

list_channels async

list_channels(request: Request)

List available messaging channels.

Source code in src/openjarvis/server/routes.py
@router.get("/v1/channels")
async def list_channels(request: Request):
    """List available messaging channels."""
    bridge = getattr(request.app.state, "channel_bridge", None)
    if bridge is None:
        return {"channels": [], "message": "Channel bridge not configured"}
    channels = bridge.list_channels()
    return {"channels": channels, "status": bridge.status().value}

channel_send async

channel_send(request: Request)

Send a message to a channel.

Source code in src/openjarvis/server/routes.py
@router.post("/v1/channels/send")
async def channel_send(request: Request):
    """Send a message to a channel."""
    bridge = getattr(request.app.state, "channel_bridge", None)
    if bridge is None:
        raise HTTPException(status_code=503, detail="Channel bridge not configured")

    body = await request.json()
    channel_name = body.get("channel", "")
    content = body.get("content", "")
    conversation_id = body.get("conversation_id", "")

    if not channel_name or not content:
        raise HTTPException(
            status_code=400, detail="'channel' and 'content' are required",
        )

    ok = bridge.send(channel_name, content, conversation_id=conversation_id)
    if not ok:
        raise HTTPException(status_code=502, detail="Failed to send message")
    return {"status": "sent", "channel": channel_name}

channel_status async

channel_status(request: Request)

Return channel bridge connection status.

Source code in src/openjarvis/server/routes.py
@router.get("/v1/channels/status")
async def channel_status(request: Request):
    """Return channel bridge connection status."""
    bridge = getattr(request.app.state, "channel_bridge", None)
    if bridge is None:
        return {"status": "not_configured"}
    return {"status": bridge.status().value}