ThreeGate/tool_exec/monty/monty_executor.py

55 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""
Monty execution helper.
This is intentionally minimal:
- No external functions
- No filesystem access
- No network
- No environment access
- Synchronous run only
If pydantic-monty is not installed, this module raises a clear error.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Dict, Optional, Tuple
@dataclass
class MontyExecResult:
output: Any
stdout: str
stderr: str
def run_monty_pure(code: str, inputs: Optional[Dict[str, Any]] = None, type_check: bool = True) -> MontyExecResult:
try:
import pydantic_monty # provided by `pydantic-monty`
except Exception as e:
raise RuntimeError(
"pydantic_monty not available. Install with: pip install pydantic-monty (or uv add pydantic-monty)."
) from e
if inputs is None:
inputs = {}
# Monty captures stdout/stderr internally, but to be robust we also capture at the runner layer.
# Here we only return the Monty output; runner will wrap stdout/stderr capture.
m = pydantic_monty.Monty(
code,
inputs=list(inputs.keys()),
external_functions=[],
script_name="tool_exec.py",
type_check=type_check,
)
# Per upstream examples, Monty can run synchronously with .run(inputs={...}). :contentReference[oaicite:2]{index=2}
out = m.run(inputs=inputs)
# We return empty strings here; the runner will capture actual stdout/stderr around this call.
return MontyExecResult(output=out, stdout="", stderr="")