velxio/backend/app/api/routes/compile_chip.py

56 lines
1.6 KiB
Python
Raw Normal View History

"""POST /api/compile-chip — compile a Velxio custom-chip C source to WASM.
The request body carries the C source. Optionally a chip.json string can be
passed for future validation; today it's stored client-side.
Response shape mirrors `compile.py`'s CompileResponse:
{ success, wasm_base64, stdout, stderr, error, byte_size }
"""
from __future__ import annotations
import logging
refactor(oss-split): introduce extension hooks for auth, DB, metrics, auto-save First phase of the OSS / pro split. Goal: open the seams so the auth/DB/admin stack can move into the private overlay (Phase 2-3) without the routes that stay in OSS (compile, libraries, simulation, iot_gateway) having to know. Backend ------- * New app/core/hooks.py — registry for record_compile, get_current_user_id, and lifespan startup tasks. Each hook is a no-op by default; overlays call register_* in register_pro(app) to plug in a real implementation. * compile.py now imports only from app.core.hooks. Drops the direct deps on app.core.dependencies, app.database.session, app.models.user, and app.services.metrics. Route signatures use `Depends(get_current_user_id)` instead of `Depends(get_current_user)`; the metric helper passes user_id through rather than a User instance. * compile_chip.py drops the unused _current_user Depends entirely. * main.py wraps the auth/DB stack import in try/except. When it succeeds (today's behavior on velxio.dev), an adapter bridges record_compile and get_current_user_id to the existing app.services.metrics + dependencies, and the create_all + ALTER TABLE migration block runs via a registered lifespan_startup hook. When it fails (the post-Phase-2 OSS image), main logs "running stateless" and skips registering anything — the routes still load and behave as no-ops for metrics + always-anonymous for auth. Frontend -------- * useAutoSaveProject becomes a skeleton: one useState + one useEffect that delegates to an installed AutoSaveImpl. installAutoSaveImpl() replaces the impl without changing hook count, so React's rules-of-hooks stay satisfied even after the impl moves out of OSS. * New hooks/autoSaveImpl.ts holds the original logic (debouncing, dirty detection, owner eligibility, fetch keepalive on unload), refactored to emit() instead of useState. It self-registers at module load; main.tsx imports it for the side effect. * AppHeader wraps the entire user-vs-login UI in a data-velxio-slot ="header-auth" boundary. Today the OSS UI still renders inside the slot — the overlay can portal-inject additional items now, and in Phase 3 the slot becomes the sole owner of header auth UX. Behavior is identical on velxio.dev (pro overlay imports everything successfully, every adapter wires up). The change is purely structural: deleting the auth/DB modules tomorrow no longer crashes OSS at import. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 23:24:51 +07:00
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from app.services.chip_compile import chip_compile_service
logger = logging.getLogger(__name__)
router = APIRouter()
class ChipCompileRequest(BaseModel):
source: str
chip_json: str | None = None
class ChipCompileResponse(BaseModel):
success: bool
wasm_base64: str | None = None
stdout: str = ""
stderr: str = ""
error: str | None = None
byte_size: int = 0
@router.post("/", response_model=ChipCompileResponse)
async def compile_chip(
request: ChipCompileRequest,
):
if not request.source or not request.source.strip():
raise HTTPException(status_code=422, detail="`source` cannot be empty.")
try:
result = await chip_compile_service.compile(request.source)
except Exception as e: # noqa: BLE001 — surface infra errors to the client
logger.exception("chip compile failed")
raise HTTPException(status_code=500, detail=str(e))
return ChipCompileResponse(**result)
@router.get("/status")
async def compile_chip_status():
"""Health endpoint — reports whether wasi-sdk + headers are available."""
return chip_compile_service.status()