harvesthealth's picture
Upload folder using huggingface_hub
f474019 verified
from fastapi import FastAPI, HTTPException, Request, Response
from pydantic import BaseModel
import subprocess
import json
import os
import sys
app = FastAPI(title="Firm Workspace Proxy")
WORKSPACE_DIR = os.environ.get("FIRM_WORKSPACE", "/app/workspace")
# Define request/response models
class QueryRequest(BaseModel):
query: str
class EntityRequest(BaseModel):
type: str
id: str
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/api-docs")
def api_docs():
return {
"endpoints": [
{
"path": "/health",
"method": "GET",
"purpose": "Returns HTTP 200 when the app is ready"
},
{
"path": "/api-docs",
"method": "GET",
"purpose": "Documents all available API endpoints"
},
{
"path": "/query",
"method": "POST",
"purpose": "Run a Firm query string",
"request": {"query": "from task | where is_completed == false"},
"response": {"result": "[...JSON array...]"}
},
{
"path": "/get",
"method": "POST",
"purpose": "Get a specific entity by type and ID",
"request": {"type": "person", "id": "john_doe"},
"response": {"result": "{...JSON object...}"}
},
{
"path": "/list/{type}",
"method": "GET",
"purpose": "List all entity IDs for a given type",
"request": {},
"response": {"result": "[...JSON array...]"}
}
]
}
@app.post("/query")
async def run_query(req: QueryRequest):
try:
# We run the firm cli directly instead of bridging stdio JSON-RPC
# which is much simpler and error-proof for a REST proxy.
proc = subprocess.run(
["firm", "query", req.query, "--workspace", WORKSPACE_DIR, "--format", "json"],
capture_output=True, text=True
)
if proc.returncode != 0:
raise HTTPException(status_code=400, detail=proc.stderr)
try:
return {"result": json.loads(proc.stdout)}
except json.JSONDecodeError:
return {"result": proc.stdout}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/get")
async def run_get(req: EntityRequest):
try:
proc = subprocess.run(
["firm", "get", req.type, req.id, "--workspace", WORKSPACE_DIR, "--format", "json"],
capture_output=True, text=True
)
if proc.returncode != 0:
raise HTTPException(status_code=400, detail=proc.stderr)
try:
return {"result": json.loads(proc.stdout)}
except json.JSONDecodeError:
return {"result": proc.stdout}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/list/{type}")
async def run_list(type: str):
try:
proc = subprocess.run(
["firm", "list", type, "--workspace", WORKSPACE_DIR, "--format", "json"],
capture_output=True, text=True
)
if proc.returncode != 0:
raise HTTPException(status_code=400, detail=proc.stderr)
try:
return {"result": json.loads(proc.stdout)}
except json.JSONDecodeError:
return {"result": proc.stdout}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)