feat: browser access (allowed_origins, CORS with Private Network Access), job cancel, Tomie/Unity adapters, benchmark

Includes earlier uncommitted work: Tomie and Unity adapters, benchmark, structured output, call metrics.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-25 18:59:28 +03:00
1 parent 13492929c6
commit f49ee90477
32 files changed
+2799 -51

No files matched your search

+17 -1
View File
@@ -3,6 +3,7 @@ import asyncio
import logging
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from .config import Settings, load_settings
from .engine import Engine
@@ -12,6 +13,9 @@ from .provider import Provider, ProviderError, autostart
from .storage import Storage
API_VERSION = 2
def create_app(settings: Settings | None = None, provider_factory=Provider):
settings = settings or load_settings()
storage = Storage(settings.database)
@@ -36,6 +40,10 @@ def create_app(settings: Settings | None = None, provider_factory=Provider):
app = FastAPI(title="Local Translator", version="0.1.0", lifespan=lifespan,
description="Local translation projects, glossary, durable jobs and protected placeholders.")
if settings.allowed_origins:
# allow_private_network answers Chrome's preflight for https page -> localhost.
app.add_middleware(CORSMiddleware, allow_origins=settings.allowed_origins, allow_methods=["GET", "POST", "PUT"],
allow_headers=["Content-Type"], expose_headers=["Location"], allow_private_network=True, max_age=600)
app.state.storage = storage
app.state.engine = engine
@@ -66,7 +74,7 @@ def create_app(settings: Settings | None = None, provider_factory=Provider):
@app.get("/health")
async def health():
return {"status": "ok", "worker_running": engine.task is not None and not engine.task.done(), "startup_errors": startup_errors}
return {"status": "ok", "api_version": API_VERSION, "worker_running": engine.task is not None and not engine.task.done(), "startup_errors": startup_errors}
@app.get("/providers")
async def providers():
@@ -145,4 +153,12 @@ def create_app(settings: Settings | None = None, provider_factory=Provider):
engine.wakeup.set()
return storage.get_job(job_id)
@app.post("/jobs/{job_id}/cancel")
async def cancel_job(job_id: str):
job = job_or_404(job_id)
if job["status"] in {"queued", "running"}:
storage.cancel(job_id)
return storage.get_job(job_id)
return job
return app