Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions api/routers/extensions.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import asyncio
import subprocess
import sys
from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, Body, HTTPException

router = APIRouter(tags=["extensions"])


@router.post("/reload")
async def reload_extensions():
async def reload_extensions(payload: dict | None = Body(default=None)):
"""
Re-scans the extensions/ folder and reloads the registry without restarting FastAPI.
Unloads all currently loaded generators before reloading.
"""
from services.generator_registry import generator_registry
generator_registry.reload()
validation_capability = None
if isinstance(payload, dict):
candidate = payload.get("validationCapability")
if isinstance(candidate, dict):
validation_capability = candidate
generator_registry.reload(validation_capability)
return {
"reloaded": True,
"models": list(generator_registry._generators.keys()),
Expand Down
16 changes: 13 additions & 3 deletions api/services/extension_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,14 +372,24 @@ def stop(self) -> None:
next load() starts a fresh subprocess.
"""
proc = self._proc
self._proc = None
self._loaded = False
if proc and proc.poll() is None:
try:
proc.kill()
proc.wait(timeout=5)
except Exception:
pass
except Exception as exc:
# Keep the process reference so callers can verify that the
# worker may still be alive and refuse to mutate its venv.
self._proc = proc
raise RuntimeError(
f"[{self.MODEL_ID}] Could not stop extension subprocess"
) from exc
if proc.poll() is None:
self._proc = proc
raise RuntimeError(
f"[{self.MODEL_ID}] Extension subprocess is still running"
)
self._proc = None
self._drain_queue()

def _drain_queue(self) -> None:
Expand Down
Loading