mirror of
https://github.com/Strategic-Automation/violin.git
synced 2026-08-14 12:33:37 +02:00
82 lines
2.4 KiB
Python
82 lines
2.4 KiB
Python
"""Shared base utilities and error serialization wrappers for tool handlers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
from functools import wraps
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from .. import command as cmd_module
|
|
from .. import state
|
|
from ..command import CheckCommandArgs
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _running_background_command(eng_dir: str, command: str) -> bool:
|
|
"""Return True if command is currently running as an acknowledged background process."""
|
|
exec_dir = _eng_path(eng_dir) / "evidence" / "executions"
|
|
if not exec_dir.exists():
|
|
return False
|
|
for path in exec_dir.glob("*.json"):
|
|
if path.name.endswith(".lock") or path.name.endswith(".tmp"):
|
|
continue
|
|
record = state.read_json(path)
|
|
if (
|
|
isinstance(record, dict)
|
|
and record.get("background")
|
|
and record.get("command") == command
|
|
and record.get("status") in {"running", "starting"}
|
|
):
|
|
return True
|
|
return False
|
|
|
|
|
|
def _eng_path(eng_dir: str) -> Path:
|
|
return state.resolve_eng_dir(eng_dir)
|
|
|
|
|
|
def _json(status_name: str, **payload) -> str:
|
|
payload.pop("status", None)
|
|
return json.dumps({"schema_version": 2, "status": status_name, **payload})
|
|
|
|
|
|
def _result(r) -> dict[str, list[str]]:
|
|
return {"errors": r.errors, "warnings": r.warnings, "infos": r.infos}
|
|
|
|
|
|
def _check_command_internal(a) -> cmd_module.CheckResult:
|
|
return cmd_module.check_command(
|
|
CheckCommandArgs(
|
|
command=a.get("command", ""),
|
|
phase=a.get("phase", ""),
|
|
eng_dir=a.get("eng_dir", ""),
|
|
scope=a.get("scope", ""),
|
|
target=a.get("target"),
|
|
session_id=a.get("session_id"),
|
|
)
|
|
)
|
|
|
|
|
|
def _call(fn, args, **kwargs) -> Any:
|
|
"""Wrap a handler function with uniform error serialisation."""
|
|
try:
|
|
return fn(args or {}, **kwargs)
|
|
except (ValueError, TypeError, OSError, KeyError) as exc:
|
|
return _json("error", error=str(exc))
|
|
except Exception as exc:
|
|
logger.exception("Unexpected handler error during execution: %s", exc)
|
|
return _json("error", error=str(exc))
|
|
|
|
|
|
def _serialise_errors(fn):
|
|
"""Keep every model-visible handler on the stable JSON response contract."""
|
|
|
|
@wraps(fn)
|
|
def wrapped(args=None, **kwargs):
|
|
return _call(fn, args, **kwargs)
|
|
|
|
return wrapped
|