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:
Morpheus
2026-07-03 20:07:00 +08:00
parent 80e51fd618
commit 6580987931
6 changed files with 187 additions and 21 deletions

View File

@@ -164,11 +164,24 @@ class SceneDetect(BaseTool):
return scenes
@staticmethod
def _escape_lavfi_movie_path(path: str) -> str:
"""Escape a path for FFmpeg lavfi movie=... without allowing filter injection."""
normalized = path.replace("\\", "/")
escaped = []
for char in normalized:
if char in "\\':,[];":
escaped.append("\\" + char)
else:
escaped.append(char)
return "".join(escaped)
def _detect_ffmpeg(self, inputs: dict[str, Any]) -> list[dict]:
"""Fallback: use FFmpeg scene change filter."""
input_path = str(inputs["input_path"])
threshold = inputs.get("threshold", 0.3)
min_scene_len = inputs.get("min_scene_length_seconds", 1.0)
escaped_input = self._escape_lavfi_movie_path(input_path)
cmd = [
"ffprobe",
@@ -176,7 +189,7 @@ class SceneDetect(BaseTool):
"-show_entries", "frame=pts_time",
"-of", "json",
"-f", "lavfi",
f"movie='{input_path.replace(chr(92), '/').replace(':', chr(92)+':')}',select='gt(scene,{threshold})'",
f"movie='{escaped_input}',select='gt(scene,{threshold})'",
]
try: