File size: 4,811 Bytes
734b5b4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | from __future__ import annotations
import sys, os, threading, webbrowser, http.server, json
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from src.core.command_router import CommandRouter
from src.core.models import JobConfig, PDFOperation
from src.core.orchestrator import OfflinePDFOrchestrator
UI_HTML = Path(__file__).parent / "web" / "orchestrator.html"
PORT = 18472
COMMAND_ROUTER = CommandRouter(project_root=Path(__file__).parent.parent.parent)
class _Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *a, **kw):
super().__init__(*a, directory=str(UI_HTML.parent), **kw)
def log_message(self, *_): pass
def do_POST(self):
if self.path == "/run":
length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(length)
payload = json.loads(body)
result = _run_job(payload)
resp = json.dumps(result).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(resp)))
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(resp)
elif self.path == "/team-plan":
length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(length)
payload = json.loads(body)
result = COMMAND_ROUTER.plan_command(payload)
resp = json.dumps(result).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(resp)))
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(resp)
else:
self.send_response(404); self.end_headers()
def do_GET(self):
if self.path == "/team-config":
result = {
"success": True,
"team": COMMAND_ROUTER.describe_team(),
"available_pipelines": COMMAND_ROUTER.orchestrator.list_available_pipelines(),
}
resp = json.dumps(result).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(resp)))
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(resp)
return
super().do_GET()
def do_OPTIONS(self):
self.send_response(204)
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers()
def _run_job(payload: dict) -> dict:
try:
ops = []
for item in payload.get("operations", []):
ops.append(PDFOperation(**item))
input_pdf = Path(payload.get("input_pdf", ""))
output_dir = Path(payload.get("output_dir", Path.home() / "pdf-output"))
if not input_pdf.exists():
return {"success": False, "error": f"Input PDF not found: {input_pdf}"}
cfg = JobConfig(
input_pdf = input_pdf,
output_dir = output_dir,
run_ocr = payload.get("force_ocr", False),
force_ocr = payload.get("force_ocr", False),
ocr_language = payload.get("ocr_language", "eng"),
operations = ops,
)
orc = OfflinePDFOrchestrator(output_dir / "_jobs")
result = orc.run(cfg)
return {
"success": result.success,
"job_id": result.job_id,
"final_pdf": str(result.final_pdf) if result.final_pdf else "",
"log_file": str(result.log_file),
"stages": result.stages,
"errors": result.errors,
}
except Exception as exc:
return {"success": False, "error": str(exc)}
def _start_server():
server = http.server.HTTPServer(("127.0.0.1", PORT), _Handler)
server.serve_forever()
def launch():
t = threading.Thread(target=_start_server, daemon=True)
t.start()
url = f"http://127.0.0.1:{PORT}/orchestrator.html"
print(f"Opening PDF Orchestrator UI at {url}")
webbrowser.open(url)
# Keep process alive
import time
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Shutting down.")
if __name__ == "__main__":
launch()
|