Spaces:
Running
Running
muralipala1504 commited on
Commit ·
ef3975d
1
Parent(s): 27bfdc0
refactor: move app to deepshell.main; keep main shim for python -m support
Browse files
deepshell-backend/deepshell/main.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from fastapi.staticfiles import StaticFiles
|
| 4 |
+
from fastapi.responses import FileResponse
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
import os
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
# LLM disabled in hard-block mode. To re-enable later, uncomment this import
|
| 10 |
+
# and the marked section in run_agent.
|
| 11 |
+
# from .llm import get_global_client
|
| 12 |
+
|
| 13 |
+
REPO_ROOT = Path(__file__).resolve().parents[2] # deepshell_modui/
|
| 14 |
+
INDEX_PATH = REPO_ROOT / "index.html"
|
| 15 |
+
STATIC_ROOT = REPO_ROOT
|
| 16 |
+
|
| 17 |
+
app = FastAPI(title="DeepShell Backend + UI")
|
| 18 |
+
|
| 19 |
+
# CORS (mostly redundant when same-origin)
|
| 20 |
+
default_origins = [
|
| 21 |
+
"http://localhost",
|
| 22 |
+
"http://localhost:8001",
|
| 23 |
+
"http://127.0.0.1",
|
| 24 |
+
"http://127.0.0.1:8001",
|
| 25 |
+
]
|
| 26 |
+
env_origins = os.getenv("CORS_ORIGINS", "")
|
| 27 |
+
extra_origins = [o.strip() for o in env_origins.split(",") if o.strip()]
|
| 28 |
+
allowed_origins = default_origins + extra_origins
|
| 29 |
+
|
| 30 |
+
app.add_middleware(
|
| 31 |
+
CORSMiddleware,
|
| 32 |
+
allow_origins=allowed_origins,
|
| 33 |
+
allow_credentials=True,
|
| 34 |
+
allow_methods=["GET", "POST", "OPTIONS"],
|
| 35 |
+
allow_headers=["*"],
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
# Serve static assets from repo root
|
| 39 |
+
app.mount("/static", StaticFiles(directory=str(STATIC_ROOT), html=False), name="static")
|
| 40 |
+
|
| 41 |
+
class ChatRequest(BaseModel):
|
| 42 |
+
prompt: str
|
| 43 |
+
|
| 44 |
+
@app.get("/")
|
| 45 |
+
def root_page():
|
| 46 |
+
if INDEX_PATH.exists():
|
| 47 |
+
return FileResponse(str(INDEX_PATH))
|
| 48 |
+
return {"status": "ok", "note": f"index.html not found at {INDEX_PATH}"}
|
| 49 |
+
|
| 50 |
+
@app.get("/app.js")
|
| 51 |
+
def get_app_js():
|
| 52 |
+
path = STATIC_ROOT / "app.js"
|
| 53 |
+
if path.exists():
|
| 54 |
+
return FileResponse(str(path), media_type="application/javascript")
|
| 55 |
+
return {"detail": "Not Found"}, 404
|
| 56 |
+
|
| 57 |
+
@app.get("/services.css")
|
| 58 |
+
def get_css():
|
| 59 |
+
path = STATIC_ROOT / "services.css"
|
| 60 |
+
if path.exists():
|
| 61 |
+
return FileResponse(str(path), media_type="text/css")
|
| 62 |
+
return {"detail": "Not Found"}, 404
|
| 63 |
+
|
| 64 |
+
@app.get("/favicon.ico")
|
| 65 |
+
def favicon():
|
| 66 |
+
# Silence 404 noise for favicon
|
| 67 |
+
return {"ok": True}
|
| 68 |
+
|
| 69 |
+
@app.get("/chat/ready")
|
| 70 |
+
def chat_ready():
|
| 71 |
+
# UI health remains OK in hard-block mode
|
| 72 |
+
return {"status": "ok"}
|
| 73 |
+
|
| 74 |
+
# Polite block message (updated wording)
|
| 75 |
+
BLOCK_MSG = (
|
| 76 |
+
"DeepShell is for Linux SysAdmin, DevOps, IaC, Cloud, and Linux scripting questions only. "
|
| 77 |
+
"Please rephrase your request in that context (e.g., commands, troubleshooting steps, "
|
| 78 |
+
"automation snippets, config examples, or cloud/infra best practices)."
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
@app.post("/chat/run-agent")
|
| 82 |
+
def run_agent(req: ChatRequest):
|
| 83 |
+
prompt = (req.prompt or "").strip()
|
| 84 |
+
if not prompt:
|
| 85 |
+
# Still respond politely rather than erroring
|
| 86 |
+
return {"answer": BLOCK_MSG}
|
| 87 |
+
|
| 88 |
+
# HARD BLOCK: always return the policy message; do not call the LLM.
|
| 89 |
+
return {"answer": BLOCK_MSG}
|
| 90 |
+
|
| 91 |
+
# To re-enable later, replace the two lines above with:
|
| 92 |
+
# client = get_global_client(os.getenv("PROVIDER", "groq"))
|
| 93 |
+
# resp = client.chat(prompt, max_tokens=1024, temperature=0.1)
|
| 94 |
+
# text = getattr(resp.choices[0].message, "content", str(resp))
|
| 95 |
+
# return {"answer": text}
|
| 96 |
+
|
| 97 |
+
def main():
|
| 98 |
+
import uvicorn
|
| 99 |
+
port = int(os.getenv("PORT", "8001"))
|
| 100 |
+
uvicorn.run("deepshell.main:app", host="0.0.0.0", port=port, reload=False)
|
| 101 |
+
|
| 102 |
+
if __name__ == "__main__":
|
| 103 |
+
main()
|