-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
121 lines (94 loc) · 3.13 KB
/
main.py
File metadata and controls
121 lines (94 loc) · 3.13 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
"""Multi-provider CLI API wrapper using FastAPI."""
import os
import asyncio
from pathlib import Path
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from backend.config import config
from backend.models import PromptRequest, PromptResponse, ProviderInfo, ProvidersListResponse
from backend.providers import registry
load_dotenv()
app = FastAPI(
title="Multi-Provider CLI API Wrapper",
description="Universal CLI API wrapper supporting multiple LLM providers",
version="2.0.0"
)
# CORS configuration
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.post("/api/ask", response_model=PromptResponse)
async def ask_llm(request: PromptRequest):
"""
Send prompt to specified provider.
Args:
request: PromptRequest with provider, prompt, and optional working_directory
Returns:
PromptResponse with success status and response/error
"""
# Determine which provider to use
provider_name = request.provider or config.DEFAULT_PROVIDER
# Get the provider
provider = registry.get(provider_name)
if not provider:
available = ", ".join(registry.list_all().keys())
raise HTTPException(
status_code=404,
detail=f"Provider '{provider_name}' not found. Available: {available}"
)
# Execute the prompt
result = await provider.execute(request.prompt, request.working_directory)
return PromptResponse(
provider=provider_name,
**result
)
@app.post("/ask", response_model=PromptResponse)
async def ask_legacy(request: PromptRequest):
"""
Legacy endpoint for backwards compatibility.
Defaults to configured default provider if none specified.
"""
if not request.provider:
request.provider = config.DEFAULT_PROVIDER
return await ask_llm(request)
@app.get("/api/providers", response_model=ProvidersListResponse)
async def list_providers():
"""
List all available providers with their status.
Returns:
ProvidersListResponse with list of provider info
"""
# Check all providers in parallel for faster response
tasks = [
provider.check_availability()
for name, provider in registry.list_all().items()
]
statuses = await asyncio.gather(*tasks)
providers_info = [
ProviderInfo(
name=provider.name,
display_name=provider.display_name,
**status
)
for (name, provider), status in zip(registry.list_all().items(), statuses)
]
return ProvidersListResponse(providers=providers_info)
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {"status": "ok"}
@app.get("/")
async def root():
"""Serve web UI."""
html_path = Path(__file__).parent / "examples" / "index.html"
return FileResponse(html_path)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host=config.HOST, port=config.PORT)