Close local release-quality gaps and reconcile workplan status
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e332-3365-77c0-8491-084e9ea33ac1
This commit is contained in:
parent
37436bb562
commit
7cd633986e
56 changed files with 462 additions and 237 deletions
|
|
@ -30,14 +30,14 @@ import time
|
|||
import uuid
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import Any
|
||||
from urllib.parse import parse_qs, urlsplit
|
||||
|
||||
from llm_connect._diagnostics import capture_diagnostics
|
||||
from llm_connect.adapter import LLMAdapter
|
||||
from llm_connect.exceptions import (
|
||||
LLMBudgetExceededError,
|
||||
LLMAPIError,
|
||||
LLMBudgetExceededError,
|
||||
LLMConfigurationError,
|
||||
LLMError,
|
||||
LLMRateLimitError,
|
||||
|
|
@ -48,15 +48,21 @@ from llm_connect.profiles import ProfiledLLMAdapter, default_runtime_profiles
|
|||
from llm_connect.usage import maybe_record_usage, suppress_auto_usage_record
|
||||
|
||||
|
||||
class _AdapterHTTPServer(ThreadingHTTPServer):
|
||||
adapter: LLMAdapter
|
||||
|
||||
|
||||
class _Handler(BaseHTTPRequestHandler):
|
||||
"""Request handler — adapter injected via server.adapter."""
|
||||
|
||||
def log_message(self, format, *args): # suppress default access log
|
||||
server: _AdapterHTTPServer
|
||||
|
||||
def log_message(self, format: str, *args: Any) -> None: # suppress default access log
|
||||
pass
|
||||
|
||||
# ── GET ────────────────────────────────────────────────────────
|
||||
|
||||
def do_GET(self):
|
||||
def do_GET(self) -> None:
|
||||
parsed = urlsplit(self.path)
|
||||
if parsed.path == "/health":
|
||||
self._respond(200, {"status": "ok"})
|
||||
|
|
@ -65,7 +71,7 @@ class _Handler(BaseHTTPRequestHandler):
|
|||
|
||||
# ── POST ───────────────────────────────────────────────────────
|
||||
|
||||
def do_POST(self):
|
||||
def do_POST(self) -> None:
|
||||
parsed = urlsplit(self.path)
|
||||
if parsed.path != "/execute":
|
||||
self._respond(404, {"error": "not found"})
|
||||
|
|
@ -96,7 +102,7 @@ class _Handler(BaseHTTPRequestHandler):
|
|||
diagnostics_enabled = debug_enabled or bool(audit_dir)
|
||||
try:
|
||||
with capture_diagnostics(diagnostics_enabled) as diagnostics:
|
||||
adapter = self.server.adapter # type: ignore[attr-defined]
|
||||
adapter = self.server.adapter
|
||||
if not adapter.validate_config(config):
|
||||
raise LLMConfigurationError(
|
||||
"Adapter rejected RunConfig",
|
||||
|
|
@ -152,9 +158,9 @@ class LLMServer:
|
|||
host: str = "127.0.0.1",
|
||||
port: int = 8080,
|
||||
) -> None:
|
||||
self._httpd = ThreadingHTTPServer((host, port), _Handler)
|
||||
self._httpd.adapter = adapter # type: ignore[attr-defined]
|
||||
self._thread: Optional[threading.Thread] = None
|
||||
self._httpd = _AdapterHTTPServer((host, port), _Handler)
|
||||
self._httpd.adapter = adapter
|
||||
self._thread: threading.Thread | None = None
|
||||
|
||||
@property
|
||||
def port(self) -> int:
|
||||
|
|
@ -163,7 +169,7 @@ class LLMServer:
|
|||
|
||||
@property
|
||||
def host(self) -> str:
|
||||
return self._httpd.server_address[0]
|
||||
return str(self._httpd.server_address[0])
|
||||
|
||||
def start(self) -> None:
|
||||
"""Start serving in a daemon background thread."""
|
||||
|
|
@ -185,7 +191,7 @@ class LLMServer:
|
|||
|
||||
def _build_adapter(
|
||||
provider: str,
|
||||
model: Optional[str],
|
||||
model: str | None,
|
||||
*,
|
||||
enable_profiles: bool = True,
|
||||
strict_profiles: bool = False,
|
||||
|
|
@ -240,7 +246,7 @@ def _error_response(exc: Exception) -> tuple[int, dict]:
|
|||
|
||||
|
||||
def _error_body(code: str, exc: Exception) -> dict:
|
||||
body = {
|
||||
body: dict[str, Any] = {
|
||||
"error": code,
|
||||
"message": _sanitize_text(_message(exc)),
|
||||
"type": exc.__class__.__name__,
|
||||
|
|
@ -260,7 +266,7 @@ def _message(exc: Exception) -> str:
|
|||
|
||||
|
||||
def _safe_context(context: dict) -> dict:
|
||||
safe = {}
|
||||
safe: dict[str, Any] = {}
|
||||
for key, value in context.items():
|
||||
lowered = str(key).lower()
|
||||
if any(secret_word in lowered for secret_word in ("key", "secret", "token", "password")):
|
||||
|
|
@ -321,7 +327,7 @@ def _safe_filename(value: str) -> str:
|
|||
return re.sub(r"[^A-Za-z0-9_.-]+", "-", value).strip("-") or "response"
|
||||
|
||||
|
||||
def main(argv=None) -> None:
|
||||
def main(argv: list[str] | None = None) -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="python -m llm_connect.server",
|
||||
description="Start llm_connect HTTP serve mode.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue