Some checks are pending
CI / lint-and-test (push) Waiting to run
* Harden leoclean no-send staging runtime * Isolate GCP leoclean runtime adapters * Verify current-main leoclean context contracts * Constrain no-send operational contracts
177 lines
7.2 KiB
Python
177 lines
7.2 KiB
Python
"""GCP-only Cloud SQL adapter over the unchanged shared Leo DB-context plugin."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from collections.abc import Callable
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
from typing import Any
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
|
|
|
|
def _load_base() -> ModuleType:
|
|
path = HERE / "base.py"
|
|
if path.is_symlink() or not path.is_file():
|
|
raise RuntimeError("bound Leo DB-context plugin is unavailable")
|
|
spec = importlib.util.spec_from_file_location("livingip_leo_db_context_base", path)
|
|
if spec is None or spec.loader is None:
|
|
raise RuntimeError("bound Leo DB-context plugin is unavailable")
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
base = _load_base()
|
|
|
|
|
|
def _load_database_snapshot(
|
|
user_message: str,
|
|
*,
|
|
conversation_history: Any = None,
|
|
hermes_home: Path | None = None,
|
|
runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
|
|
) -> dict[str, Any]:
|
|
"""Load one private, excerpt-bearing Cloud SQL snapshot without VPS fallback."""
|
|
|
|
query = str(user_message or "")[: base.MAX_QUERY_CHARS]
|
|
contextual = getattr(base, "_contextual_retrieval_query", lambda value, _history: (value, []))
|
|
retrieval_query, retrieval_anchors = contextual(query, conversation_history)
|
|
resolve_home = getattr(
|
|
base,
|
|
"_resolve_hermes_home",
|
|
lambda explicit: explicit or Path(os.getenv("HERMES_HOME", str(Path.home() / ".hermes"))),
|
|
)
|
|
home = resolve_home(hermes_home)
|
|
teleo_kb = home / "bin" / "teleo-kb"
|
|
query_sha256 = hashlib.sha256(query.encode("utf-8")).hexdigest()
|
|
base_record: dict[str, Any] = {
|
|
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
|
|
"event": "pre_llm_call",
|
|
"query_sha256": query_sha256,
|
|
"retrieval_query_sha256": hashlib.sha256(retrieval_query.encode("utf-8")).hexdigest(),
|
|
"retrieval_anchor_count": len(retrieval_anchors),
|
|
"retrieval_anchors_sha256": hashlib.sha256(
|
|
json.dumps(retrieval_anchors, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
|
).hexdigest(),
|
|
"source": "teleo-kb context --include-excerpts",
|
|
}
|
|
if not teleo_kb.is_file() or not os.access(teleo_kb, os.X_OK):
|
|
record = base_record | {"status": "error", "error": "teleo_kb_missing", "injected": True}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, "teleo_kb_missing")
|
|
|
|
timeout = int(os.getenv("LEO_DB_CONTEXT_TIMEOUT_SECONDS", str(base.DEFAULT_TIMEOUT_SECONDS)))
|
|
command = [
|
|
str(teleo_kb),
|
|
"context",
|
|
query,
|
|
"--retrieval-query",
|
|
retrieval_query,
|
|
]
|
|
for anchor in retrieval_anchors:
|
|
command.extend(("--retrieval-anchor", anchor))
|
|
command.extend(
|
|
[
|
|
"--limit",
|
|
str(base.CONTEXT_CLAIM_LIMIT),
|
|
"--context-limit",
|
|
str(base.CONTEXT_ROW_LIMIT),
|
|
"--include-excerpts",
|
|
"--format",
|
|
"json",
|
|
]
|
|
)
|
|
try:
|
|
completed = runner(command, capture_output=True, text=True, timeout=timeout, check=False)
|
|
except subprocess.TimeoutExpired:
|
|
record = base_record | {"status": "error", "error": "timeout", "injected": True}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, "timeout")
|
|
except OSError as exc:
|
|
record = base_record | {"status": "error", "error": type(exc).__name__, "injected": True}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, type(exc).__name__)
|
|
|
|
if completed.returncode != 0:
|
|
reason = f"teleo_kb_exit_{completed.returncode}"
|
|
record = base_record | {"status": "error", "error": reason, "injected": True}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, reason)
|
|
|
|
try:
|
|
payload = json.loads(completed.stdout)
|
|
contracts = payload.get("operational_contracts")
|
|
if not isinstance(contracts, list) or not all(isinstance(item, dict) for item in contracts):
|
|
raise ValueError("operational_contracts_missing")
|
|
claims = payload.get("claims", [])
|
|
if not isinstance(claims, list) or not all(isinstance(item, dict) for item in claims):
|
|
raise ValueError("claims_missing")
|
|
context_rows = payload.get("context_rows", [])
|
|
if not isinstance(context_rows, list) or not all(isinstance(item, dict) for item in context_rows):
|
|
raise ValueError("context_rows_missing")
|
|
compiled_response = payload.get("compiled_response")
|
|
if compiled_response is not None and not isinstance(compiled_response, str):
|
|
raise ValueError("compiled_response_invalid")
|
|
contract_mode = payload.get("runtime_contract_mode")
|
|
if contract_mode not in {"claim_evidence_challenge", "general", "review_only_candidate"}:
|
|
raise ValueError("runtime_contract_mode_invalid")
|
|
if base._requires_database_truth(query) and contract_mode == "general":
|
|
record = base_record | {
|
|
"status": "error",
|
|
"error": "gcp_contract_surface_not_yet_supported",
|
|
"injected": True,
|
|
}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, "gcp_contract_surface_not_yet_supported")
|
|
retrieval_payload, injected_rows_sha256 = base._compact_retrieval_payload(
|
|
claims,
|
|
context_rows,
|
|
payload.get("retrieval_receipt"),
|
|
)
|
|
retrieval_receipt = base._retrieval_receipt_trace(
|
|
payload.get("retrieval_receipt"),
|
|
injected_rows_sha256=injected_rows_sha256,
|
|
)
|
|
except (json.JSONDecodeError, TypeError, ValueError) as exc:
|
|
record = base_record | {"status": "error", "error": str(exc), "injected": True}
|
|
base._trace(record)
|
|
return base._error_snapshot(query, query_sha256, str(exc))
|
|
|
|
contract_json = json.dumps(contracts, sort_keys=True, separators=(",", ":"))
|
|
record = base_record | {
|
|
"status": "ok",
|
|
"injected": True,
|
|
"contract_ids": [str(item.get("id") or "") for item in contracts],
|
|
"contract_sha256": hashlib.sha256(contract_json.encode("utf-8")).hexdigest(),
|
|
"compiled_response_available": bool(compiled_response),
|
|
"runtime_contract_mode": contract_mode,
|
|
"database_reasoning_protocol_version": base.DATABASE_REASONING_PROTOCOL_VERSION,
|
|
}
|
|
if retrieval_receipt is not None:
|
|
record["retrieval_receipt"] = retrieval_receipt
|
|
base._trace(record)
|
|
return {
|
|
"status": "ok",
|
|
"query_sha256": query_sha256,
|
|
"contracts": contracts,
|
|
"compiled_response": compiled_response,
|
|
"requires_database_truth": bool({str(item.get("id") or "") for item in contracts} - {"reply_budget"}),
|
|
"database_reasoning_protocol_version": base.DATABASE_REASONING_PROTOCOL_VERSION,
|
|
"context": base._format_context(contracts, retrieval_payload, injected_rows_sha256),
|
|
}
|
|
|
|
|
|
base._load_database_snapshot = _load_database_snapshot
|
|
|
|
|
|
def register(ctx: Any) -> None:
|
|
base.register(ctx)
|