fix(headless): Apply review suggestions for track 'manual_slop_headless_20260225'
This commit is contained in:
24
gui_2.py
24
gui_2.py
@@ -307,6 +307,7 @@ class App:
|
||||
self._discussion_names_dirty = True
|
||||
|
||||
def create_api(self) -> FastAPI:
|
||||
"""Creates and configures the FastAPI application for headless mode."""
|
||||
api = FastAPI(title="Manual Slop Headless API")
|
||||
|
||||
class GenerateRequest(BaseModel):
|
||||
@@ -322,22 +323,26 @@ class App:
|
||||
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
|
||||
|
||||
async def get_api_key(header_key: str = Depends(api_key_header)):
|
||||
"""Validates the API key from the request header against configuration."""
|
||||
headless_cfg = self.config.get("headless", {})
|
||||
config_key = headless_cfg.get("api_key", "").strip()
|
||||
env_key = os.environ.get("SLOP_API_KEY", "").strip()
|
||||
target_key = env_key or config_key
|
||||
if not target_key:
|
||||
return None
|
||||
# If no key is configured, we must deny access by default for security
|
||||
raise HTTPException(status_code=403, detail="API Key not configured on server")
|
||||
if header_key == target_key:
|
||||
return header_key
|
||||
raise HTTPException(status_code=403, detail="Could not validate API Key")
|
||||
|
||||
@api.get("/health")
|
||||
def health():
|
||||
"""Basic health check endpoint."""
|
||||
return {"status": "ok"}
|
||||
|
||||
@api.get("/status", dependencies=[Depends(get_api_key)])
|
||||
def status():
|
||||
"""Returns the current status of the AI provider and active project."""
|
||||
return {
|
||||
"provider": self.current_provider,
|
||||
"model": self.current_model,
|
||||
@@ -348,6 +353,7 @@ class App:
|
||||
|
||||
@api.get("/api/v1/pending_actions", dependencies=[Depends(get_api_key)])
|
||||
def pending_actions():
|
||||
"""Lists all PowerShell scripts awaiting manual confirmation."""
|
||||
actions = []
|
||||
with self._pending_dialog_lock:
|
||||
# Include multi-actions from headless mode
|
||||
@@ -368,6 +374,7 @@ class App:
|
||||
|
||||
@api.post("/api/v1/confirm/{action_id}", dependencies=[Depends(get_api_key)])
|
||||
def confirm_action(action_id: str, req: ConfirmRequest):
|
||||
"""Approves or denies a pending PowerShell script execution."""
|
||||
success = self.resolve_pending_action(action_id, req.approved)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail=f"Action ID {action_id} not found")
|
||||
@@ -375,6 +382,7 @@ class App:
|
||||
|
||||
@api.get("/api/v1/sessions", dependencies=[Depends(get_api_key)])
|
||||
def list_sessions():
|
||||
"""Lists all available session log files."""
|
||||
log_dir = Path("logs")
|
||||
if not log_dir.exists():
|
||||
return []
|
||||
@@ -382,6 +390,7 @@ class App:
|
||||
|
||||
@api.get("/api/v1/sessions/{filename}", dependencies=[Depends(get_api_key)])
|
||||
def get_session(filename: str):
|
||||
"""Retrieves the content of a specific session log file."""
|
||||
if ".." in filename or "/" in filename or "\\" in filename:
|
||||
raise HTTPException(status_code=400, detail="Invalid filename")
|
||||
log_path = Path("logs") / filename
|
||||
@@ -395,6 +404,7 @@ class App:
|
||||
|
||||
@api.delete("/api/v1/sessions/{filename}", dependencies=[Depends(get_api_key)])
|
||||
def delete_session(filename: str):
|
||||
"""Deletes a specific session log file."""
|
||||
if ".." in filename or "/" in filename or "\\" in filename:
|
||||
raise HTTPException(status_code=400, detail="Invalid filename")
|
||||
log_path = Path("logs") / filename
|
||||
@@ -408,6 +418,7 @@ class App:
|
||||
|
||||
@api.get("/api/v1/context", dependencies=[Depends(get_api_key)])
|
||||
def get_context():
|
||||
"""Returns the current file and screenshot context configuration."""
|
||||
return {
|
||||
"files": self.files,
|
||||
"screenshots": self.screenshots,
|
||||
@@ -417,6 +428,7 @@ class App:
|
||||
|
||||
@api.post("/api/v1/generate", dependencies=[Depends(get_api_key)])
|
||||
def generate(req: GenerateRequest):
|
||||
"""Triggers an AI generation request using the current project context."""
|
||||
if not req.prompt.strip():
|
||||
raise HTTPException(status_code=400, detail="Prompt cannot be empty")
|
||||
|
||||
@@ -486,6 +498,7 @@ class App:
|
||||
|
||||
@api.post("/api/v1/stream", dependencies=[Depends(get_api_key)])
|
||||
async def stream(req: GenerateRequest):
|
||||
"""Placeholder for streaming AI generation responses (Not yet implemented)."""
|
||||
# Streaming implementation would require ai_client to support yield-based responses.
|
||||
# Currently added as a placeholder to satisfy spec requirements.
|
||||
raise HTTPException(status_code=501, detail="Streaming endpoint (/api/v1/stream) is not yet supported in this version.")
|
||||
@@ -971,6 +984,15 @@ class App:
|
||||
return output
|
||||
|
||||
def resolve_pending_action(self, action_id: str, approved: bool):
|
||||
"""Resolves a pending PowerShell script confirmation by its ID.
|
||||
|
||||
Args:
|
||||
action_id: The unique identifier for the pending action.
|
||||
approved: True if the script should be executed, False otherwise.
|
||||
|
||||
Returns:
|
||||
bool: True if the action was found and resolved, False otherwise.
|
||||
"""
|
||||
with self._pending_dialog_lock:
|
||||
if action_id in self._pending_actions:
|
||||
dialog = self._pending_actions[action_id]
|
||||
|
||||
Reference in New Issue
Block a user