File size: 5,276 Bytes
07afba2
 
 
 
 
 
0f3f790
07afba2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0f3f790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f69a7e
0f3f790
 
 
 
 
 
 
 
70cbf2c
0f3f790
70cbf2c
 
 
 
 
 
 
 
 
0f3f790
 
07afba2
 
 
 
 
 
 
 
 
 
0abffce
 
 
 
 
 
 
 
 
 
 
 
 
6f69a7e
0abffce
 
 
 
 
 
0f3f790
374f911
916d312
07afba2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0f3f790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c8ee813
f846e62
0f3f790
 
07afba2
 
 
 
 
 
 
 
 
 
 
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import os
import sys
from pathlib import Path

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from dotenv import load_dotenv, find_dotenv


# Ensure project root on sys.path for package imports
ROOT_DIR = Path(__file__).resolve().parent
if str(ROOT_DIR) not in sys.path:
    sys.path.append(str(ROOT_DIR))

# Load environment (HF Spaces will inject secrets via env vars)
load_dotenv(find_dotenv(), override=True)


app = FastAPI(title="Flagship AI", version="0.1.0")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# --- Static assets (shared Suite styles/header) ---
SUITE_STATIC_DIR = (ROOT_DIR / "Suite" / "app" / "static").resolve()
app.mount("/static", StaticFiles(directory=str(SUITE_STATIC_DIR)), name="static")


# --- Include routers from agents that already use prefixed routes ---
# UX Prototyper uses router prefix '/ux'
try:
    from AIDesign.app.main import router as ux_router  # type: ignore

    app.include_router(ux_router)
except Exception:
    # Optional: keep the app booting even if module missing
    pass

# Slack Knowledge Bot uses router prefix '/slack'
try:
    from AIIntegration.app.main import router as slack_router  # type: ignore

    app.include_router(slack_router)
except Exception:
    pass

# AI Readiness Audit uses router prefix '/audit'
try:
    print("Attempting to import AIReadiness...")
    from AIReadiness.app.main import router as audit_router  # type: ignore
    print(f"Successfully imported AIReadiness router: {audit_router}")
    print(f"Router prefix: {audit_router.prefix}")
    app.include_router(audit_router)
    print("Successfully included AIReadiness router")
except Exception as e:
    print(f"Failed to import AIReadiness router: {e}")
    import traceback
    traceback.print_exc()
    pass

# Additional prefixed routers
for mod_path, name in (
    ("AIAccessibility.app.main", "access_router"),
    ("AIAutomation.app.main", "automation_router"),
    ("AIStrategy.app.main", "strategy_router"),
    ("AIFit.app.main", "fit_router"),
    ("AIDual.app.main", "dual_router"),
    ("AIQuiz.app.main", "quiz_router"),
    ("AIRoute.app.main", "route_router"),
    ("AISaas.app.main", "saas_router"),
):
    try:
        print(f"Importing {mod_path}...")
        module = __import__(mod_path, fromlist=["router"])  # type: ignore
        router = getattr(module, "router")
        print(f"Successfully imported {name}: {router}")
        print(f"Router routes: {[route.path for route in router.routes]}")
        app.include_router(router)  # type: ignore
        print(f"Successfully included {name}")
    except Exception as e:
        print(f"Failed to import {mod_path}: {e}")
        import traceback
        traceback.print_exc()
        pass


# --- Mount full apps where clean scoping is needed ---
# Opportunity Planner (AISolutions) has unprefixed routes; mount under '/solutions'
try:
    from AISolutions.app.main import app as solutions_app  # type: ignore

    app.mount("/solutions", solutions_app)
except Exception:
    pass

# Include routers with proper prefixes
try:
    from AIArchitecture.app.main import router as arch_router  # type: ignore
    app.include_router(arch_router)
except Exception:
    pass

try:
    from AICommerce.app.main import router as commerce_router  # type: ignore
    app.include_router(commerce_router)
except Exception:
    pass

# AIAutomation is now included in the loop above

try:
    from AIHealthcare.app.main import router as healthcare_router  # type: ignore
    app.include_router(healthcare_router)
except Exception:
    pass

# These routers are already included by the loop above


# --- Index routes for top-level and agent landings ---
@app.get("/")
def suite_index() -> FileResponse:
    """Serve the Flagship Suite landing page."""
    return FileResponse((SUITE_STATIC_DIR / "index.html").as_posix())


@app.get("/ux")
def ux_index() -> FileResponse:
    base = ROOT_DIR / "AIDesign" / "app" / "static" / "index.html"
    return FileResponse(base.as_posix())


@app.get("/slack")
def slack_index() -> FileResponse:
    base = ROOT_DIR / "AIIntegration" / "app" / "static" / "index.html"
    return FileResponse(base.as_posix())

# Audit route is now handled by the AIReadiness router

# Static index shortcuts for mounted apps and prefixed routers
@app.get("/solutions/")
def solutions_index_redirect() -> RedirectResponse:
    # Mounted app handles this; ensure trailing slash variant resolves
    return RedirectResponse(url="/solutions/")

# These routes are now handled by their respective routers

@app.get("/triage")
def triage_index() -> FileResponse:
    base = ROOT_DIR / "AIHealthcare" / "app" / "static" / "index.html"
    return FileResponse(base.as_posix())

# Invoice route is now handled by the AIAutomation router

# These routes are now handled by their respective routers


# Optional health endpoint for the aggregator
@app.get("/healthz")
def healthz() -> dict:
    return {
        "status": "ok",
        "openai_key": bool(os.getenv("OPENAI_API_KEY")),
        "version": "0.1.0",
    }