Files

150 lines
5.7 KiB
Python

"""FastAPI route definitions for Bridge V1.2 with UTF-8 support."""
from __future__ import annotations
import sys
from pathlib import Path
from fastapi import APIRouter, HTTPException, Request
import adapters as adapter_registry
from core.run_manager import RunManager
from models.schemas import CreateRunRequest, HealthResponse, RunResponse, RunStatus
from policy.guard import check as policy_check
def safe_print(text):
"""Print with UTF-8 encoding fallback for Windows CP1252."""
try:
print(text)
except UnicodeEncodeError:
sys.stdout.buffer.write(text.encode('utf-8', errors='replace'))
sys.stdout.buffer.write(b'\n')
RUNS_DIR = Path(__file__).resolve().parents[1] / "runs"
_manager = RunManager(RUNS_DIR)
router = APIRouter()
@router.get("/health", response_model=HealthResponse)
def health():
"""Returns server status and per-adapter mode (real/stub)."""
import os
from adapters import openai_adapter
from controller.decision_model import DECISION_MODE
print(f"[ENCODING DEBUG] sys.getdefaultencoding() = {sys.getdefaultencoding()}")
print(f"[ENCODING DEBUG] sys.getfilesystemencoding() = {sys.getfilesystemencoding()}")
print(f"[ENCODING DEBUG] LANG = {os.environ.get('LANG', 'NOT SET')}")
print(f"[ENCODING DEBUG] PYTHONIOENCODING = {os.environ.get('PYTHONIOENCODING', 'NOT SET')}")
return HealthResponse(
status="ok",
adapters=adapter_registry.available(),
openai_mode=openai_adapter.mode(),
decision_backend=DECISION_MODE,
ollama_model=os.environ.get("OLLAMA_MODEL", "qwen2.5:7b"),
)
@router.post("/runs", response_model=RunResponse, status_code=201)
def create_run(body: CreateRunRequest):
"""One-shot run: create -> instruct -> execute -> persist -> done|forced.
The response is the final completed state — status is never 'running'
when this endpoint returns.
FORCE AGENT ROUTING: All requests are forced to use 'agent' adapter.
No fallback, no alternative adapters, no direct LLM calls.
"""
safe_print("=== RUNS ENDPOINT CALLED ===")
safe_print("=== FORCE AGENT ROUTING ENABLED ===")
# Force agent adapter - ignore request body adapter
forced_adapter = "agent"
safe_print(f"=== USING ADAPTER: {forced_adapter} ===")
# Handle greetings directly - no need to run agent
goal_lower = body.goal.strip().lower()
greetings = {
"привет": "Привет! Я Agent Maxim. Напиши, что хочешь найти - я помогу!",
"hi": "Hi! I'm Agent Maxim. What would you like to find?",
"hello": "Hello! I'm Agent Maxim. What would you like to find?",
"здравствуй": "Здравствуй! Я Agent Maxim. Напиши, что хочешь найти - я помогу!",
"приветик": "Приветик! Чем могу помочь?",
"йо": "Йо! Чем могу помочь?",
"прив": "Прив! Что ищем?",
"здорово": "Здорово! Чем могу помочь?",
"йоу": "Йоу! Что хочешь найти?",
}
if goal_lower in greetings:
from datetime import datetime, timezone
now = datetime.now(timezone.utc).isoformat()
safe_print(f"=== GREETING DETECTED: {goal_lower} - returning quick response ===")
return RunResponse(
run_id=body.run_id or "greeting",
goal=body.goal,
status="done",
adapter=forced_adapter,
adapter_mode="greeting",
instruction=body.goal,
response=greetings[goal_lower],
error=None,
exit_code=0,
created_at=now,
updated_at=now,
)
# DEBUG: Log encoding details
safe_print(f"[ENCODING DEBUG] Raw goal: {body.goal}")
safe_print(f"[ENCODING DEBUG] Repr goal: {repr(body.goal)}")
safe_print(f"[ENCODING DEBUG] Goal type: {type(body.goal)}")
safe_print(f"[ENCODING DEBUG] Goal bytes: {body.goal.encode('utf-8')}")
# DEBUG: Log adapter info
safe_print(f"[FORCE ROUTING] Requested adapter: {body.adapter}")
safe_print(f"[FORCE ROUTING] Forced adapter: {forced_adapter}")
safe_print(f"[FORCE ROUTING] No fallback, no alternatives - agent only")
adapter_mod = adapter_registry.get(forced_adapter)
if adapter_mod is None:
safe_print("=== RETURNING RESPONSE (ERROR) ===")
raise HTTPException(
status_code=500,
detail=f"Agent adapter not available - this should never happen",
)
try:
state = _manager.execute_run(
goal=body.goal,
adapter_name=forced_adapter,
adapter_fn=adapter_mod.execute, # type: ignore[attr-defined]
guard_fn=policy_check,
run_id=body.run_id,
)
except ValueError as exc:
safe_print("=== RETURNING RESPONSE (ERROR) ===")
raise HTTPException(status_code=409, detail=str(exc)) from exc
safe_print("=== RETURNING RESPONSE (SUCCESS) ===")
return RunResponse(**state)
@router.get("/runs/{run_id}", response_model=RunResponse)
def get_run(run_id: str):
"""Retrieve persisted run state."""
state = _manager.get_run(run_id)
if state is None:
raise HTTPException(status_code=404, detail=f"run '{run_id}' not found")
return RunResponse(**state)
@router.post("/runs/{run_id}/cancel")
def cancel_run(run_id: str):
"""Cancel a running or pending run."""
state = _manager.get_run(run_id)
if state is None:
raise HTTPException(status_code=404, detail=f"run '{run_id}' not found")
_manager.cancel_run(run_id)
return {"message": f"run '{run_id}' cancellation requested"}