forked from EverMind-AI/EverOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
150 lines (129 loc) · 5.14 KB
/
Copy pathapp.py
File metadata and controls
150 lines (129 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""FastAPI application factory.
Wires CORS + the project's middleware stack + global exception handler +
lifespan, and registers the public routes (``/health``, ``/metrics``).
"""
from __future__ import annotations
import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from everos.core.lifespan import (
LifespanProvider,
MetricsLifespanProvider,
TracingLifespanProvider,
build_lifespan,
)
from everos.core.middleware import (
DEFAULT_CORS_ALLOW_CREDENTIALS,
DEFAULT_CORS_ALLOW_HEADERS,
DEFAULT_CORS_ALLOW_METHODS,
DEFAULT_CORS_ORIGINS,
ProfileMiddleware,
PrometheusMiddleware,
RequestIdMiddleware,
)
from everos.core.observability.logging import get_logger
from .exception_handlers import register_handlers
from .lifespans import (
CascadeLifespanProvider,
LanceDBLifespanProvider,
LLMLifespanProvider,
OmeLifespanProvider,
ParserLifespanProvider,
SqliteLifespanProvider,
)
from .routes import (
get,
health,
knowledge,
memorize,
metrics,
ome,
search,
)
logger = get_logger(__name__)
def _docs_enabled() -> bool:
"""Enable docs endpoints (/docs, /redoc, /openapi.json) only in dev."""
return os.environ.get("ENV", "prod").upper() == "DEV"
def create_app(
*,
cors_origins: list[str] | None = None,
cors_allow_credentials: bool = DEFAULT_CORS_ALLOW_CREDENTIALS,
cors_allow_methods: list[str] | None = None,
cors_allow_headers: list[str] | None = None,
lifespan_providers: list[LifespanProvider] | None = None,
) -> FastAPI:
"""Build the FastAPI application instance.
Args:
cors_origins: Allowed CORS origins (default: ``["*"]``).
cors_allow_credentials: Whether to allow credentials (default: True).
cors_allow_methods: Allowed CORS methods (default: ``["*"]``).
cors_allow_headers: Allowed CORS headers (default: ``["*"]``).
lifespan_providers: Optional list of LifespanProvider; defaults to
``[TracingLifespanProvider(), MetricsLifespanProvider(),
LLMLifespanProvider(), ParserLifespanProvider(),
SqliteLifespanProvider(), LanceDBLifespanProvider(),
CascadeLifespanProvider(), OmeLifespanProvider()]``.
Returns:
FastAPI: Configured application instance.
"""
enable_docs = _docs_enabled()
if lifespan_providers is None:
lifespan_providers = [
TracingLifespanProvider(),
MetricsLifespanProvider(),
LLMLifespanProvider(),
ParserLifespanProvider(),
SqliteLifespanProvider(),
LanceDBLifespanProvider(),
CascadeLifespanProvider(),
OmeLifespanProvider(),
]
from everos import __version__
app = FastAPI(
title="everos",
version=__version__,
description="md-first memory extraction framework",
lifespan=build_lifespan(lifespan_providers),
docs_url="/docs" if enable_docs else None,
redoc_url="/redoc" if enable_docs else None,
openapi_url="/openapi.json" if enable_docs else None,
)
# Exception handlers
register_handlers(app)
# Middleware order: earlier `add_middleware` calls become inner, later ones outer.
# CORS innermost (matches base_app.py legacy pattern).
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins or DEFAULT_CORS_ORIGINS,
allow_credentials=cors_allow_credentials,
allow_methods=cors_allow_methods or DEFAULT_CORS_ALLOW_METHODS,
allow_headers=cors_allow_headers or DEFAULT_CORS_ALLOW_HEADERS,
)
app.add_middleware(PrometheusMiddleware)
app.add_middleware(ProfileMiddleware)
# Outermost: every request gets a request id before any other middleware
# or handler runs, so all logs + the response header carry it.
app.add_middleware(RequestIdMiddleware)
# Infra endpoints — deliberately unversioned.
app.include_router(health.router)
app.include_router(metrics.router)
# Business API — served under both /api/v2 (canonical, cloud-aligned name)
# and /api/v1 (legacy compatibility alias, removable in a future major).
# The same router object is mounted twice, so both prefixes resolve to the
# exact same handlers; FastAPI's default operationId embeds the path, so
# the two copies get distinct OpenAPI ids automatically (no collision).
# v1 and v2 stay identical by construction — see test_api_versioning.
# v1 first — legacy alias, behavior identical.
app.include_router(memorize.router, prefix="/api/v1")
app.include_router(search.router, prefix="/api/v1")
app.include_router(get.router, prefix="/api/v1")
app.include_router(ome.router, prefix="/api/v1")
app.include_router(knowledge.router, prefix="/api/v1")
# v2 — cloud-aligned name, same routers.
app.include_router(memorize.router, prefix="/api/v2")
app.include_router(search.router, prefix="/api/v2")
app.include_router(get.router, prefix="/api/v2")
app.include_router(ome.router, prefix="/api/v2")
app.include_router(knowledge.router, prefix="/api/v2")
logger.info("app_created", docs_enabled=enable_docs)
return app