Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
59 changes: 59 additions & 0 deletions python/valuecell/server/api/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""FastAPI application factory for ValueCell Server."""

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager

from ..config.settings import get_settings


def create_app() -> FastAPI:
"""Create and configure FastAPI application."""
settings = get_settings()

@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
print(
f"ValueCell Server starting up on {settings.API_HOST}:{settings.API_PORT}..."
)
yield
# Shutdown
print("ValueCell Server shutting down...")

app = FastAPI(
title="ValueCell Server API",
description="A community-driven, multi-agent platform for financial applications",
version=settings.APP_VERSION,
lifespan=lifespan,
docs_url="/docs" if settings.API_DEBUG else None,
redoc_url="/redoc" if settings.API_DEBUG else None,
)

# Add middleware
_add_middleware(app, settings)

# Add routes
_add_routes(app)

return app


def _add_middleware(app: FastAPI, settings) -> None:
"""Add middleware to the application."""
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# Custom logging middleware removed


def _add_routes(app: FastAPI) -> None:
"""Add routes to the application."""
# app.include_router(health.router, prefix="/health", tags=["health"])
# app.include_router(agents.router, prefix="/api/v1", tags=["agents"])
Empty file.
Empty file.
Empty file.
85 changes: 85 additions & 0 deletions python/valuecell/server/config/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""Settings configuration for ValueCell Server."""

import os
from pathlib import Path
from functools import lru_cache


class Settings:
"""Server configuration settings."""

def __init__(self):
"""Initialize settings from environment variables."""
# Application Configuration
self.APP_NAME = os.getenv("APP_NAME", "ValueCell Server")
self.APP_VERSION = os.getenv("APP_VERSION", "0.1.0")
self.APP_ENVIRONMENT = os.getenv("APP_ENVIRONMENT", "development")

# API Configuration
self.API_HOST = os.getenv("API_HOST", "localhost")
self.API_PORT = int(os.getenv("API_PORT", "8000"))
self.API_DEBUG = os.getenv("API_DEBUG", "false").lower() == "true"

# CORS Configuration
cors_origins = os.getenv("CORS_ORIGINS", "*")
self.CORS_ORIGINS = cors_origins.split(",") if cors_origins != "*" else ["*"]

# Database Configuration
self.DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./valuecell.db")
self.DB_ECHO = os.getenv("DB_ECHO", "false").lower() == "true"

# Redis Configuration
self.REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")

# Security Configuration
self.SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key-here")
self.ACCESS_TOKEN_EXPIRE_MINUTES = int(
os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30")
)

# Logging Configuration
self.LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
self.LOG_FORMAT = os.getenv("LOG_FORMAT", "json")

# File Paths
self.BASE_DIR = Path(__file__).parent.parent.parent
self.LOGS_DIR = self.BASE_DIR / "logs"
self.LOGS_DIR.mkdir(exist_ok=True)

# Agent Configuration
self.AGENT_TIMEOUT = int(os.getenv("AGENT_TIMEOUT", "300")) # 5 minutes
self.MAX_CONCURRENT_AGENTS = int(os.getenv("MAX_CONCURRENT_AGENTS", "10"))

# External APIs
self.OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
self.FINNHUB_API_KEY = os.getenv("FINNHUB_API_KEY")
self.ALPHA_VANTAGE_API_KEY = os.getenv("ALPHA_VANTAGE_API_KEY")

@property
def is_development(self) -> bool:
"""Check if running in development mode."""
return self.APP_ENVIRONMENT == "development"

@property
def is_production(self) -> bool:
"""Check if running in production mode."""
return self.APP_ENVIRONMENT == "production"

def get_database_config(self) -> dict:
"""Get database configuration."""
return {
"url": self.DATABASE_URL,
"echo": self.DB_ECHO,
}

def get_redis_config(self) -> dict:
"""Get Redis configuration."""
return {
"url": self.REDIS_URL,
}


@lru_cache()
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()
Empty file.
5 changes: 5 additions & 0 deletions python/valuecell/server/db/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Database models for ValueCell Server."""

from .base import Base

__all__ = ["Base"]
10 changes: 10 additions & 0 deletions python/valuecell/server/db/models/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Base model for ValueCell Server."""

from sqlalchemy.ext.declarative import declarative_base

# Create the base class for all models
Base = declarative_base()

# Alternative approach using modern SQLAlchemy 2.0 style
# class Base(DeclarativeBase):
# pass
Empty file.
22 changes: 22 additions & 0 deletions python/valuecell/server/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Main entry point for ValueCell Server Backend."""

import uvicorn
from .api.app import create_app
from .config.settings import get_settings


def main():
"""Start the server."""
settings = get_settings()
app = create_app()

uvicorn.run(
app,
host=settings.API_HOST,
port=settings.API_PORT,
reload=settings.API_DEBUG,
)


if __name__ == "__main__":
main()
Empty file.