1 parent
52f1770515
commit
96be3fdeb3
6 files changed
+429
-46
No files matched your search
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
Phase 1 #1A: Skills API Router
|
||||
POST /api/skills/ppt/generate - Generate PPTX
|
||||
GET /api/skills/ppt/download/{instance_id} - Download PPTX
|
||||
POST /api/skills/seo/analyze - SEO analysis
|
||||
POST /api/skills/research/generate - Investment research
|
||||
GET /api/skills/status/{instance_id} - Check execution status
|
||||
"""
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
from app.auth import get_current_user, get_current_tenant
|
||||
from app.skill_runtime import PPTSkillRuntime, SEOSkillRuntime, ResearchSkillRuntime
|
||||
from app.database import SessionLocal
|
||||
import os
|
||||
|
||||
router = APIRouter(tags=["技能执行"])
|
||||
|
||||
class PPTRequest(BaseModel):
|
||||
content: str
|
||||
template: str = "business"
|
||||
slides: int = 5
|
||||
|
||||
class SEORequest(BaseModel):
|
||||
url: str = ""
|
||||
keywords: str = ""
|
||||
|
||||
class ResearchRequest(BaseModel):
|
||||
symbol: str
|
||||
|
||||
@router.post("/ppt/generate")
|
||||
async def generate_ppt(req: PPTRequest, user=Depends(get_current_user), tenant=Depends(get_current_tenant)):
|
||||
"""Generate PPT from text content using AI + python-pptx."""
|
||||
runtime = PPTSkillRuntime(
|
||||
skill_id="ppt-generator",
|
||||
user_id=user["id"],
|
||||
tenant_id=tenant
|
||||
)
|
||||
result = await runtime.execute({"content": req.content, "template": req.template, "slides": req.slides})
|
||||
return {"code": 0, "data": result, "message": "PPT generated" if result["status"] == "ready" else "Failed"}
|
||||
|
||||
@router.get("/ppt/download/{instance_id}")
|
||||
async def download_ppt(instance_id: str, user=Depends(get_current_user)):
|
||||
"""Download generated PPTX file."""
|
||||
from sqlalchemy import text
|
||||
db = SessionLocal()
|
||||
row = db.execute(text(
|
||||
"SELECT result FROM skill_instances WHERE id = :id AND user_id = :uid"
|
||||
), {"id": instance_id, "uid": user["id"]}).fetchone()
|
||||
db.close()
|
||||
|
||||
if not row:
|
||||
raise HTTPException(404, "Instance not found")
|
||||
# Find workspace path
|
||||
ws = f"/app/workspace/*/{user['id']}/ppt-generator/{instance_id}/output.pptx"
|
||||
import glob
|
||||
matches = glob.glob(ws)
|
||||
if matches:
|
||||
return FileResponse(matches[0], media_type="application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
filename="presentation.pptx")
|
||||
raise HTTPException(404, "PPTX file not found")
|
||||
|
||||
@router.post("/seo/analyze")
|
||||
async def analyze_seo(req: SEORequest, user=Depends(get_current_user), tenant=Depends(get_current_tenant)):
|
||||
"""Analyze SEO for a URL/keyword."""
|
||||
runtime = SEOSkillRuntime(
|
||||
skill_id="seo-optimizer",
|
||||
user_id=user["id"],
|
||||
tenant_id=tenant
|
||||
)
|
||||
result = await runtime.execute({"url": req.url, "keywords": req.keywords})
|
||||
return {"code": 0, "data": result, "message": "SEO analysis complete"}
|
||||
|
||||
@router.post("/research/generate")
|
||||
async def generate_research(req: ResearchRequest, user=Depends(get_current_user), tenant=Depends(get_current_tenant)):
|
||||
"""Generate investment research report."""
|
||||
runtime = ResearchSkillRuntime(
|
||||
skill_id="investment-research",
|
||||
user_id=user["id"],
|
||||
tenant_id=tenant
|
||||
)
|
||||
result = await runtime.execute({"symbol": req.symbol})
|
||||
return {"code": 0, "data": result, "message": "Research generated"}
|
||||
|
||||
@router.get("/status/{instance_id}")
|
||||
async def get_skill_status(instance_id: str, user=Depends(get_current_user)):
|
||||
"""Check skill execution status."""
|
||||
from sqlalchemy import text
|
||||
db = SessionLocal()
|
||||
row = db.execute(text(
|
||||
"SELECT status, result, error, created_at FROM skill_instances WHERE id = :id AND user_id = :uid"
|
||||
), {"id": instance_id, "uid": user["id"]}).fetchone()
|
||||
db.close()
|
||||
if not row:
|
||||
raise HTTPException(404, "Instance not found")
|
||||
return {"code": 0, "data": {"status": row[0], "result": row[1], "error": row[2],
|
||||
"created_at": str(row[3])}}
|
||||
Reference in new issue
Block a user