mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-25 01:20:18 +08:00
fix: harden tool governance and subprocess safety
- persist budget warnings and approved paid-tool decisions - support binary dependency declarations - include stderr/stdout details for failed subprocesses - escape lavfi movie paths used by ffmpeg scene detection Verification: - python3 tests/tools/test_cost_tracker_governance.py - python3 tests/tools/test_scene_detect_lavfi_escape.py - python3 tests/tools/test_base_tool_dependencies.py - python3 -m py_compile ...
This commit is contained in:
@@ -209,8 +209,9 @@ class BaseTool(ABC):
|
||||
def check_dependencies(self) -> None:
|
||||
"""Verify all dependencies are installed. Raises DependencyError if not."""
|
||||
for dep in self.dependencies:
|
||||
if dep.startswith("cmd:"):
|
||||
cmd_name = dep[4:]
|
||||
if dep.startswith(("cmd:", "binary:")):
|
||||
prefix = "cmd:" if dep.startswith("cmd:") else "binary:"
|
||||
cmd_name = dep[len(prefix):]
|
||||
if shutil.which(cmd_name) is None:
|
||||
raise DependencyError(
|
||||
f"Command {cmd_name!r} not found. {self.install_instructions}"
|
||||
@@ -329,20 +330,28 @@ class BaseTool(ABC):
|
||||
exe = shutil.which(resolved_cmd[0])
|
||||
if exe:
|
||||
resolved_cmd[0] = exe
|
||||
return subprocess.run(
|
||||
resolved_cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
# Force UTF-8 decoding. The default uses the OS locale (cp1252 on
|
||||
# Windows), which raises UnicodeDecodeError on a subprocess that
|
||||
# emits Unicode/emoji (e.g. Remotion's progress output), killing the
|
||||
# reader thread and potentially swallowing the real error text.
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
timeout=timeout,
|
||||
cwd=cwd,
|
||||
check=True,
|
||||
)
|
||||
try:
|
||||
return subprocess.run(
|
||||
resolved_cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
# Force UTF-8 decoding. The default uses the OS locale (cp1252 on
|
||||
# Windows), which raises UnicodeDecodeError on a subprocess that
|
||||
# emits Unicode/emoji (e.g. Remotion's progress output), killing the
|
||||
# reader thread and potentially swallowing the real error text.
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
timeout=timeout,
|
||||
cwd=cwd,
|
||||
check=True,
|
||||
)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
stderr = (exc.stderr or "").strip()
|
||||
stdout = (exc.stdout or "").strip()
|
||||
detail = stderr or stdout or str(exc)
|
||||
raise RuntimeError(
|
||||
f"Command failed with exit code {exc.returncode}: {' '.join(resolved_cmd)}\n{detail}"
|
||||
) from exc
|
||||
|
||||
|
||||
class DependencyError(Exception):
|
||||
|
||||
Reference in New Issue
Block a user