Merge remote-tracking branch 'origin/main' into codex/repair-pr-442

# Conflicts:
#	.env.example
This commit is contained in:
calesthio
2026-08-13 09:07:59 -07:00
105 changed files with 5907 additions and 403 deletions

View File

@@ -0,0 +1,158 @@
"""Contracts for cloud mesh generation and Blender world rendering."""
from __future__ import annotations
import json
import subprocess
from pathlib import Path
import jsonschema
from tools.base_tool import ToolStatus
from tools.graphics import atlas_3d, fal_3d
from tools.graphics.atlas_3d import Atlas3D
from tools.graphics import blender_world
from tools.graphics.blender_world import BlenderWorld, first_missing_frame
from tools.graphics.fal_3d import Fal3D
from tools.tool_registry import ToolRegistry
class _Response:
def __init__(self, payload=None, content=b""):
self._payload = payload
self.content = content
def json(self):
return self._payload
def raise_for_status(self):
return None
def test_registry_discovers_separate_3d_capabilities():
registry = ToolRegistry()
registry.discover("tools")
assert {tool.name for tool in registry.get_by_capability("3d_asset_generation")} >= {
"atlas_3d", "fal_3d"
}
assert {tool.name for tool in registry.get_by_capability("3d_world_rendering")} >= {
"blender_world"
}
def test_atlas_cost_matrix_and_missing_key(monkeypatch, tmp_path):
for key in ("ATLASCLOUD_API_KEY", "ATLAS_CLOUD_API_KEY", "ATLAS_API_KEY"):
monkeypatch.delenv(key, raising=False)
tool = Atlas3D()
assert tool.get_status() == ToolStatus.UNAVAILABLE
assert tool.estimate_cost({"texture": False}) == 0.22
assert tool.estimate_cost({"texture": True, "texture_quality": "standard"}) == 0.33
assert tool.estimate_cost({"texture": True, "texture_quality": "detailed", "geometry_quality": "detailed"}) == 0.66
result = tool.execute({"prompt": "a cottage", "output_path": str(tmp_path / "cottage.glb")})
assert not result.success
assert "key" in (result.error or "").lower()
def test_fal_cost_matrix_and_input_validation(monkeypatch, tmp_path):
monkeypatch.delenv("FAL_KEY", raising=False)
monkeypatch.delenv("FAL_AI_API_KEY", raising=False)
tool = Fal3D()
assert tool.estimate_cost({"operation": "reconstruct_objects"}) == 0.02
assert tool.estimate_cost({"operation": "image_to_3d", "enable_pbr": False}) == 0.225
assert tool.estimate_cost({"operation": "image_to_3d", "enable_pbr": True}) == 0.375
result = tool.execute({"operation": "text_to_3d", "output_path": str(tmp_path / "asset.glb")})
assert not result.success
def test_blender_doctor_reports_detected_runtime(monkeypatch, tmp_path):
executable = tmp_path / "blender"
executable.write_bytes(b"")
monkeypatch.setattr(blender_world, "find_blender", lambda: executable)
monkeypatch.setattr(blender_world.subprocess, "run", lambda *args, **kwargs: subprocess.CompletedProcess(
args=args[0], returncode=0, stdout="OPENMONTAGE_BLENDER=4.5.10 LTS\n", stderr="",
))
result = BlenderWorld().execute({"operation": "doctor"})
assert result.success, result.error
assert result.data["version_line"].startswith("OPENMONTAGE_BLENDER=4.5.10")
def test_blender_doctor_explains_missing_optional_runtime(monkeypatch):
monkeypatch.setattr(blender_world, "find_blender", lambda: None)
result = BlenderWorld().execute({"operation": "doctor"})
assert not result.success
assert "Blender not found" in (result.error or "")
def test_blender_resume_finds_first_missing_contiguous_frame(tmp_path):
prefix = tmp_path / "frame-"
for frame in (1, 2, 4):
(tmp_path / f"frame-{frame:04d}.png").write_bytes(b"png")
assert first_missing_frame(prefix, 1, 5) == 3
(tmp_path / "frame-0003.png").write_bytes(b"png")
assert first_missing_frame(prefix, 1, 4) is None
def test_asset_manifest_accepts_generated_mesh_type():
schema = json.loads(Path("schemas/artifacts/asset_manifest.schema.json").read_text(encoding="utf-8"))
jsonschema.validate({
"version": "1.0",
"assets": [{
"id": "hero-cottage",
"type": "3d_asset",
"path": "assets/3d/hero-cottage.glb",
"source_tool": "atlas_3d",
"scene_id": "village",
}],
}, schema)
def test_atlas_success_downloads_glb_and_provenance(monkeypatch, tmp_path):
monkeypatch.setenv("ATLASCLOUD_API_KEY", "test-key")
monkeypatch.setattr(atlas_3d.time, "sleep", lambda _seconds: None)
monkeypatch.setattr(atlas_3d.requests, "post", lambda *args, **kwargs: _Response({"data": {"id": "pred-1"}}))
def fake_get(url, **_kwargs):
if "prediction/pred-1" in url:
return _Response({"data": {"status": "completed", "files": [{
"type": "glb", "url": "https://cdn.example/asset.glb",
}]}})
return _Response(content=b"glb-bytes")
monkeypatch.setattr(atlas_3d.requests, "get", fake_get)
output = tmp_path / "asset.glb"
result = Atlas3D().execute({"prompt": "a weathered cottage", "output_path": str(output)})
assert result.success, result.error
assert output.read_bytes() == b"glb-bytes"
provenance = json.loads(output.with_suffix(".provenance.json").read_text(encoding="utf-8"))
assert provenance["prediction_id"] == "pred-1"
assert provenance["model"] == "tripo-h3.1/text-to-3d"
def test_fal_success_downloads_glb_and_provenance(monkeypatch, tmp_path):
monkeypatch.setenv("FAL_KEY", "test-key")
monkeypatch.setattr(fal_3d.time, "sleep", lambda _seconds: None)
monkeypatch.setattr(fal_3d.requests, "post", lambda *args, **kwargs: _Response({
"request_id": "req-1",
"status_url": "https://queue.example/status",
"response_url": "https://queue.example/result",
}))
def fake_get(url, **_kwargs):
if url.endswith("/status"):
return _Response({"status": "COMPLETED"})
if url.endswith("/result"):
return _Response({"model_urls": {"glb": {
"url": "https://cdn.example/asset.glb", "content_type": "model/gltf-binary",
}}})
return _Response(content=b"fal-glb")
monkeypatch.setattr(fal_3d.requests, "get", fake_get)
output = tmp_path / "fal-asset.glb"
result = Fal3D().execute({
"operation": "text_to_3d", "prompt": "a stone bridge", "output_path": str(output),
})
assert result.success, result.error
assert output.read_bytes() == b"fal-glb"
provenance = json.loads(output.with_suffix(".provenance.json").read_text(encoding="utf-8"))
assert provenance["request_id"] == "req-1"
assert provenance["provider"] == "fal"

View File

@@ -0,0 +1,94 @@
import shutil
import subprocess
import math
import struct
import wave
from pathlib import Path
import pytest
from tools.audio.audio_mixer import AudioMixer
pytestmark = pytest.mark.skipif(
shutil.which("ffmpeg") is None or shutil.which("ffprobe") is None,
reason="ffmpeg and ffprobe are required",
)
def _tone(path: Path, frequency: int, duration: float) -> None:
subprocess.run(
[
"ffmpeg", "-y", "-f", "lavfi", "-i",
f"sine=frequency={frequency}:duration={duration}", str(path),
],
capture_output=True,
check=True,
timeout=30,
)
def _duration(path: Path) -> float:
result = subprocess.run(
[
"ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "csv=p=0", str(path),
],
capture_output=True,
check=True,
text=True,
timeout=30,
)
return float(result.stdout.strip())
def _tail_rms(path: Path, start_seconds: float, end_seconds: float) -> float:
with wave.open(str(path), "rb") as handle:
sample_width = handle.getsampwidth()
assert sample_width == 2
frame_rate = handle.getframerate()
handle.setpos(int(start_seconds * frame_rate))
raw = handle.readframes(int((end_seconds - start_seconds) * frame_rate))
samples = struct.unpack(f"<{len(raw) // 2}h", raw)
return math.sqrt(sum(sample * sample for sample in samples) / len(samples))
def test_full_mix_can_pin_the_composition_length(tmp_path) -> None:
speech = tmp_path / "speech.wav"
music = tmp_path / "music.wav"
output = tmp_path / "mix.wav"
_tone(speech, 440, 1)
_tone(music, 220, 3)
result = AudioMixer().execute({
"operation": "full_mix",
"tracks": [
{"path": str(speech), "role": "speech"},
{"path": str(music), "role": "music"},
],
"ducking": {"enabled": True},
"normalize": False,
"target_duration": 3,
"output_path": str(output),
})
assert result.success, result.error
assert result.data["target_duration"] == 3
assert _duration(output) == pytest.approx(3.0, abs=0.15)
assert _tail_rms(output, 2.0, 2.5) > 100
@pytest.mark.parametrize("target", [0, -1, "not-a-number"])
def test_full_mix_rejects_invalid_target_duration(tmp_path, target) -> None:
tone = tmp_path / "tone.wav"
_tone(tone, 440, 0.25)
result = AudioMixer().execute({
"operation": "full_mix",
"tracks": [{"path": str(tone), "role": "speech"}],
"target_duration": target,
"output_path": str(tmp_path / "mix.wav"),
})
assert result.success is False
assert "target_duration" in result.error

View File

@@ -0,0 +1,28 @@
import sys
from unittest.mock import MagicMock
from PIL import Image
def test_bg_remove_selects_model_through_rembg_session(monkeypatch, tmp_path) -> None:
fake_rembg = MagicMock()
fake_rembg.new_session.return_value = "selected-session"
fake_rembg.remove.side_effect = lambda image, **kwargs: image.convert("RGBA")
monkeypatch.setitem(sys.modules, "rembg", fake_rembg)
input_path = tmp_path / "input.png"
Image.new("RGB", (8, 8), (10, 20, 30)).save(input_path)
from tools.enhancement.bg_remove import BgRemove
result = BgRemove().execute({
"input_path": str(input_path),
"output_path": str(tmp_path / "output.png"),
"model": "isnet-general-use",
})
assert result.success, result.error
fake_rembg.new_session.assert_called_once_with("isnet-general-use")
kwargs = fake_rembg.remove.call_args.kwargs
assert kwargs["session"] == "selected-session"
assert "model_name" not in kwargs

View File

@@ -0,0 +1,177 @@
import json
from pathlib import Path
import pytest
from tools.video.video_compose import VideoCompose
def test_cinematic_cut_adapter_builds_a_sequential_timeline() -> None:
scenes = VideoCompose._cuts_to_cinematic_scenes([
{
"id": "v1",
"source": "clip.mp4",
"in_seconds": 2,
"out_seconds": 6,
"transition_in": "cut",
"transition_out": "none",
},
{
"id": "title",
"source": "",
"type": "hero_title",
"text": "The signal arrives",
"in_seconds": 0,
"out_seconds": 3,
},
])
assert scenes[0] == {
"id": "v1",
"startSeconds": 0.0,
"durationSeconds": 4.0,
"kind": "video",
"src": "clip.mp4",
"trimBeforeSeconds": 2.0,
"trimAfterSeconds": 6.0,
"playbackRate": 1.0,
"fadeInFrames": 0,
"fadeOutFrames": 0,
}
assert scenes[1]["kind"] == "title"
assert scenes[1]["startSeconds"] == 4.0
assert scenes[1]["text"] == "The signal arrives"
def test_cinematic_cut_adapter_preserves_playback_speed() -> None:
scenes = VideoCompose._cuts_to_cinematic_scenes([
{
"id": "fast",
"source": "clip.mp4",
"in_seconds": 2,
"out_seconds": 6,
"speed": 2,
}
])
assert scenes[0]["durationSeconds"] == 2
assert scenes[0]["playbackRate"] == 2
@pytest.mark.parametrize("uri_style", ["standard", "legacy_windows"])
def test_remotion_media_staging_decodes_file_uris(tmp_path, uri_style) -> None:
source = tmp_path / "clip with space.mp4"
source.write_bytes(b"video")
public_dir = tmp_path / "public"
uri = source.as_uri()
if uri_style == "legacy_windows" and len(source.drive) == 2:
uri = f"file://{source.drive}{source.as_posix()[2:]}".replace(" ", "%20")
props = {"scenes": [{"src": uri}]}
staged_count = VideoCompose._stage_remotion_media(props, public_dir)
assert staged_count == 1
assert props["scenes"][0]["src"] != uri
assert (public_dir / props["scenes"][0]["src"]).read_bytes() == b"video"
def test_remotion_render_adapts_cuts_and_stages_local_video(monkeypatch, tmp_path) -> None:
source = tmp_path / "source.mp4"
source.write_bytes(b"not-a-real-video")
output = tmp_path / "render.mp4"
captured = {}
def fake_run_command(self, command, **kwargs):
captured["command"] = command
captured["timeout"] = kwargs["timeout"]
props_arg = next(arg for arg in command if arg.startswith("--props="))
captured["props"] = json.loads(Path(props_arg.split("=", 1)[1]).read_text())
public_arg = next(arg for arg in command if arg.startswith("--public-dir="))
public_dir = Path(public_arg.split("=", 1)[1])
captured["staged_exists_during_render"] = (
public_dir / captured["props"]["scenes"][0]["src"]
).exists()
output.write_bytes(b"rendered")
monkeypatch.setattr(VideoCompose, "run_command", fake_run_command)
result = VideoCompose()._remotion_render({
"edit_decisions": {
"renderer_family": "cinematic-trailer",
"cuts": [
{
"id": "v1",
"source": str(source),
"in_seconds": 0,
"out_seconds": 2,
}
],
},
"output_path": str(output),
})
assert result.success, result.error
assert "cuts" not in captured["props"]
assert captured["props"]["scenes"][0]["kind"] == "video"
assert captured["staged_exists_during_render"] is True
assert result.data["staged_media_count"] == 1
def test_remotion_timeout_scales_with_scene_count(monkeypatch, tmp_path) -> None:
output = tmp_path / "render.mp4"
captured = {}
def fake_run_command(self, command, **kwargs):
captured["timeout"] = kwargs["timeout"]
output.write_bytes(b"rendered")
monkeypatch.setattr(VideoCompose, "run_command", fake_run_command)
cuts = [
{
"id": f"title-{index}",
"source": "",
"type": "hero_title",
"text": str(index),
"in_seconds": 0,
"out_seconds": 1,
}
for index in range(50)
]
result = VideoCompose()._remotion_render({
"edit_decisions": {"renderer_family": "cinematic-trailer", "cuts": cuts},
"output_path": str(output),
})
assert result.success, result.error
assert captured["timeout"] == 750
def test_remotion_render_preserves_direct_cinematic_scenes(monkeypatch, tmp_path) -> None:
output = tmp_path / "render.mp4"
captured = {}
def fake_run_command(self, command, **kwargs):
props_arg = next(arg for arg in command if arg.startswith("--props="))
captured["props"] = json.loads(Path(props_arg.split("=", 1)[1]).read_text())
output.write_bytes(b"rendered")
monkeypatch.setattr(VideoCompose, "run_command", fake_run_command)
scene = {
"id": "authored",
"kind": "title",
"text": "Keep me",
"startSeconds": 0,
"durationSeconds": 1,
}
result = VideoCompose()._remotion_render({
"composition_data": {
"renderer_family": "cinematic-trailer",
"scenes": [scene],
},
"output_path": str(output),
})
assert result.success, result.error
assert captured["props"]["scenes"] == [scene]

View File

@@ -0,0 +1,59 @@
from dataclasses import dataclass
import pytest
import tools.video.stock_sources as stock_sources
from tools.video.corpus_builder import CorpusBuilder
@dataclass
class _Candidate:
clip_id: str
class _Source:
name = "fake"
def __init__(self, count: int) -> None:
self.count = count
def is_available(self) -> bool:
return True
def search(self, query, filters):
return [_Candidate(f"clip-{index}") for index in range(self.count)]
@pytest.fixture
def run_builder(monkeypatch, tmp_path):
def run(count: int, processor):
monkeypatch.setattr(stock_sources, "available_sources", lambda: [_Source(count)])
monkeypatch.setattr(stock_sources, "source_summary", lambda: {})
monkeypatch.setattr(CorpusBuilder, "_process_candidate", processor)
return CorpusBuilder().execute({
"corpus_dir": str(tmp_path / f"corpus-{count}"),
"queries": [{"query": "city at night"}],
"max_new_clips": 50,
})
return run
def test_all_candidate_failures_fail_closed_with_diagnostics(run_builder) -> None:
def broken_clip_stack(*args, **kwargs):
raise AttributeError("BaseModelOutput has no attribute norm")
result = run_builder(4, broken_clip_stack)
assert result.success is False
assert result.data["candidates_seen"] == 4
assert result.data["clips_failed"] == 4
assert "corpus index is empty" in result.error
assert "BaseModelOutput" in result.error
def test_no_candidates_is_a_valid_empty_search(run_builder) -> None:
result = run_builder(0, lambda *args, **kwargs: None)
assert result.success is True
assert result.data["candidates_seen"] == 0

View File

@@ -0,0 +1,97 @@
from pathlib import Path
from types import SimpleNamespace
import pytest
def test_blank_google_location_uses_documented_default(monkeypatch) -> None:
monkeypatch.setenv("GOOGLE_CLOUD_LOCATION", "")
from tools.google_credentials import resolve_google_location
assert resolve_google_location() == "us-central1"
def test_google_music_requests_the_global_vertex_location(monkeypatch, tmp_path) -> None:
monkeypatch.setenv("GOOGLE_API_KEY", "test-key")
import tools.google_credentials as credentials
captured = {}
def stop_before_network(http_options=None, location=None):
captured["location"] = location
raise RuntimeError("stop before network")
monkeypatch.setattr(credentials, "get_genai_client", stop_before_network)
from tools.audio.google_music import GoogleMusic
result = GoogleMusic().execute({
"prompt": "solo piano",
"output_path": str(tmp_path / "music.mp3"),
})
assert result.success is False
assert captured["location"] == "global"
class _VideoAsset:
uri = None
def __init__(self, video_bytes):
self.video_bytes = video_bytes
def save(self, path):
Path(path).write_bytes(self.video_bytes or b"")
class _Models:
def __init__(self, video_bytes):
self.video_bytes = video_bytes
def generate_videos(self, **kwargs):
asset = _VideoAsset(self.video_bytes)
generated = SimpleNamespace(video=asset)
response = SimpleNamespace(generated_videos=[generated])
return SimpleNamespace(done=True, error=None, response=response)
class _VertexClient:
vertexai = True
def __init__(self, video_bytes):
self.models = _Models(video_bytes)
self.files = SimpleNamespace(
download=lambda **kwargs: pytest.fail("Vertex must not call files.download")
)
@pytest.mark.parametrize(
("video_bytes", "expected_success"),
[(b"VIDEO_BYTES", True), (None, False)],
)
def test_veo_accepts_vertex_and_requires_inline_bytes(
monkeypatch, tmp_path, video_bytes, expected_success
) -> None:
monkeypatch.setenv("GOOGLE_API_KEY", "test-key")
import tools.google_credentials as credentials
monkeypatch.setattr(
credentials,
"get_genai_client",
lambda http_options=None, location=None: _VertexClient(video_bytes),
)
from tools.video.veo_video import VeoVideo
output = tmp_path / "video.mp4"
result = VeoVideo().execute({
"backend": "google",
"prompt": "wind moving across grassland",
"output_path": str(output),
})
assert result.success is expected_success
if expected_success:
assert output.read_bytes() == b"VIDEO_BYTES"
else:
assert "without inline bytes" in result.error

View File

@@ -250,6 +250,11 @@ def test_runtime_check_succeeds_when_npm_resolves(monkeypatch):
"_resolve_npm_package",
classmethod(lambda cls: {"version": "0.4.5"}),
)
monkeypatch.setattr(
HyperFramesCompose,
"_probe_cli",
classmethod(lambda cls: {"status": "ok"}),
)
rc = HyperFramesCompose()._runtime_check()
# Local binaries must still pass for this to go green.
if rc["node_major"] is None or not rc["ffmpeg_available"] or not rc["npx_available"]:
@@ -259,6 +264,31 @@ def test_runtime_check_succeeds_when_npm_resolves(monkeypatch):
assert rc["reasons"] == []
def test_runtime_check_fails_when_published_cli_crashes(monkeypatch):
monkeypatch.setattr(
HyperFramesCompose,
"_resolve_npm_package",
classmethod(lambda cls: {"version": "0.7.89"}),
)
monkeypatch.setattr(
HyperFramesCompose,
"_probe_cli",
classmethod(
lambda cls: {
"error": 'doctor failed: The "file" argument must be of type string'
}
),
)
rc = HyperFramesCompose()._runtime_check()
if rc["node_major"] is None or not rc["ffmpeg_available"] or not rc["npx_available"]:
pytest.skip("Local runtime floor not met on this machine")
assert rc["runtime_available"] is False
assert rc["cli_probe_error"] is not None
assert any("not executable" in reason for reason in rc["reasons"])
def test_video_compose_render_engines_follow_hyperframes_runtime_check(monkeypatch):
"""Regression: `video_compose.get_info()['render_engines']['hyperframes']`
must track the true availability, not just the local-binary floor.

View File

@@ -213,8 +213,9 @@ def test_upscale_build_upsampler_uses_signature_guard(monkeypatch):
# Build a fake RealESRGANer whose __init__ DOES accept device=
class FakeRealESRGANer:
def __init__(self, *, scale, model_path, model, dni_weight, half, device=None):
def __init__(self, *, scale, model_path, model, dni_weight, half, tile=0, tile_pad=10, device=None):
self.called_with_device = device
self.called_with_tile = tile
fake_realesrganer_cls = FakeRealESRGANer
monkeypatch.setitem(sys.modules, "torch", fake_torch)
@@ -239,6 +240,7 @@ def test_upscale_build_upsampler_uses_signature_guard(monkeypatch):
tool = upscale.Upscale()
result = tool._build_upsampler(scale=4, model_name="RealESRGAN_x4plus", denoise_strength=0.5, face_enhance=False)
assert result.called_with_device == "device(mps)"
assert result.called_with_tile == 256
def test_upscale_build_upsampler_skips_device_when_unsupported(monkeypatch):
@@ -252,8 +254,9 @@ def test_upscale_build_upsampler_skips_device_when_unsupported(monkeypatch):
# Build a fake RealESRGANer whose __init__ does NOT accept device=
class FakeRealESRGANerNoDevice:
def __init__(self, *, scale, model_path, model, dni_weight, half):
def __init__(self, *, scale, model_path, model, dni_weight, half, tile=0, tile_pad=10):
self.called_with_device = None # no device param
self.called_with_tile = tile
fake_realesrganer_cls = FakeRealESRGANerNoDevice
monkeypatch.setitem(sys.modules, "torch", fake_torch)
@@ -279,6 +282,7 @@ def test_upscale_build_upsampler_skips_device_when_unsupported(monkeypatch):
# Should NOT raise TypeError about unexpected keyword argument 'device'
result = tool._build_upsampler(scale=4, model_name="RealESRGAN_x4plus", denoise_strength=0.5, face_enhance=False)
assert result.called_with_device is None
assert result.called_with_tile == 256
# ------------------------------------------------------------------

View File

@@ -0,0 +1,59 @@
import shutil
import subprocess
from pathlib import Path
import pytest
from tools.video.video_compose import VideoCompose
pytestmark = pytest.mark.skipif(
shutil.which("ffmpeg") is None or shutil.which("ffprobe") is None,
reason="ffmpeg and ffprobe are required",
)
def _run(command: list[str]) -> None:
subprocess.run(command, capture_output=True, check=True, timeout=30)
def test_external_audio_mux_adds_audible_stream_without_changing_video_length(tmp_path) -> None:
video = tmp_path / "video.mp4"
audio = tmp_path / "audio.wav"
_run([
"ffmpeg", "-y", "-f", "lavfi", "-i",
"color=c=red:s=320x180:d=2:r=30",
"-c:v", "libx264", "-pix_fmt", "yuv420p", str(video),
])
_run([
"ffmpeg", "-y", "-f", "lavfi", "-i",
"sine=frequency=440:duration=1", str(audio),
])
result = VideoCompose()._mux_external_audio(video, audio)
assert result.success, result.error
streams = subprocess.run(
[
"ffprobe", "-v", "error", "-show_entries",
"stream=codec_type", "-of", "csv=p=0", str(video),
],
capture_output=True,
check=True,
text=True,
timeout=30,
).stdout.splitlines()
duration = float(subprocess.run(
[
"ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "csv=p=0", str(video),
],
capture_output=True,
check=True,
text=True,
timeout=30,
).stdout.strip())
assert "video" in streams
assert "audio" in streams
assert duration == pytest.approx(2.0, abs=0.15)

View File

@@ -0,0 +1,45 @@
import json
import zipfile
from pathlib import Path
from tools.graphics.threejs_asset_catalog import CATALOGS, ThreeJSAssetCatalog
def test_catalog_list_is_rights_explicit():
result = ThreeJSAssetCatalog().execute({"operation": "list"})
assert result.success
assert result.data["catalogs"]
assert all(item["license"] == "CC0-1.0" for item in result.data["catalogs"].values())
def test_catalog_install_inventories_gltf(tmp_path, monkeypatch):
source_zip = tmp_path / "fixture.zip"
with zipfile.ZipFile(source_zip, "w") as package:
package.writestr("Models/GLTF format/Tree.gltf", json.dumps({"asset": {"version": "2.0"}}))
package.writestr("Models/GLTF format/Tree.bin", b"mesh")
package.writestr("Textures/tree.png", b"texture")
fixture_id = "fixture-catalog"
monkeypatch.setitem(CATALOGS, fixture_id, {
"title": "Fixture",
"source_url": "https://example.test/source",
"download_url": "https://example.test/catalog.zip",
"license": "CC0-1.0",
"license_url": "https://creativecommons.org/publicdomain/zero/1.0/",
"tags": ["fixture"],
})
def fake_download(_url: str, destination: Path) -> None:
destination.write_bytes(source_zip.read_bytes())
monkeypatch.setattr("tools.graphics.threejs_asset_catalog._download", fake_download)
output = tmp_path / "installed"
result = ThreeJSAssetCatalog().execute({
"operation": "install",
"catalog_id": fixture_id,
"output_path": str(output),
})
assert result.success, result.error
assert result.data["model_count"] == 1
assert result.data["texture_count"] == 1
assert (output / "catalog-manifest.json").exists()

View File

@@ -0,0 +1,243 @@
"""Contracts for semantic Three.js world generation and atelier rendering."""
from __future__ import annotations
import hashlib
import json
import subprocess
from pathlib import Path
from tools.base_tool import ToolResult
from tools.graphics.threejs_world import ThreeJSWorld
from tools.tool_registry import ToolRegistry
from tools.video.hyperframes_compose import HyperFramesCompose
from tools.video.video_compose import VideoCompose
def _world_spec(duration: float = 12.0) -> dict:
return {
"version": "1.0",
"title": "The Luminous Divide",
"seed": 260805248,
"explicit_constraints": ["one continuous explorable world"],
"inferred_details": ["cyan emissive accents provide visual continuity"],
"world": {
"size": 96,
"resolution": 72,
"elevation_scale": 12,
"water_level": -1.5,
},
"regions": [
{
"id": "wetlands",
"center": [-0.45, 0.15],
"radius": 0.9,
"landform": "basin",
"color": "#204a43",
"accent_color": "#71f7c4",
"scatter": {"tree": 18, "rock": 8, "crystal": 6},
},
{
"id": "rift",
"center": [0.5, -0.1],
"radius": 0.9,
"landform": "canyon",
"color": "#503040",
"accent_color": "#ff765f",
"scatter": {"tree": 0, "rock": 18, "crystal": 9},
},
],
"landmarks": [
{
"id": "threshold-ring",
"type": "ring",
"region_id": "wetlands",
"position": [-22, 0, 8],
"scale": 3.5,
}
],
"camera_path": [
{"time": 0, "position": [-42, 23, 38], "target": [-18, 0, 4]},
{"time": duration / 2, "position": [0, 16, 24], "target": [10, 0, -4]},
{"time": duration, "position": [42, 25, -34], "target": [20, 0, -5]},
],
}
def test_threejs_world_contract_and_registry_discovery():
tool = ThreeJSWorld()
assert tool.capability == "3d_world_generation"
assert tool.provider == "threejs"
assert "threejs-world-generation" in tool.agent_skills
assert {"cinematic", "semantic", "wireframe"} == set(
tool.input_schema["properties"]["render_mode"]["enum"]
)
registry = ToolRegistry()
registry.discover("tools")
assert "threejs_world" in {
discovered.name
for discovered in registry.get_by_capability("3d_world_generation")
}
def test_threejs_world_validate_emits_worldclaw_diagnostics():
result = ThreeJSWorld().execute(
{"operation": "validate", "world_spec": _world_spec(), "duration_seconds": 12}
)
assert result.success, result.error
report = result.data["report"]
assert report["valid"] is True
assert report["stats"]["region_count"] == 2
assert report["stats"]["terrain_triangles"] > 0
assert set(report["diagnostic_passes"]) == {"cinematic", "semantic", "wireframe"}
assert report["review_views"] == [
"global",
"regional",
"walk",
"semantic",
"wireframe",
]
def test_threejs_world_build_is_deterministic_and_editable(tmp_path):
workspaces = [tmp_path / "first", tmp_path / "second"]
hashes = []
for workspace in workspaces:
result = ThreeJSWorld().execute(
{
"operation": "build",
"world_spec": _world_spec(),
"output_path": str(workspace),
"duration_seconds": 12,
"width": 1280,
"height": 720,
"render_mode": "semantic",
}
)
assert result.success, result.error
for filename in (
"index.html",
"world.css",
"world-runtime.js",
"world.json",
"world-spec.js",
"world-report.json",
"hyperframes.json",
):
assert (workspace / filename).is_file()
index = (workspace / "index.html").read_text(encoding="utf-8")
assert "--world-width: 1280px" in index
assert 'data-render-mode="semantic"' in index
hashes.append(
hashlib.sha256((workspace / "world-spec.js").read_bytes()).hexdigest()
)
assert hashes[0] == hashes[1]
assert json.loads((workspaces[0] / "world.json").read_text(encoding="utf-8"))[
"seed"
] == 260805248
def test_threejs_world_rejects_incomplete_camera_path():
spec = _world_spec()
spec["camera_path"][-1]["time"] = 11
result = ThreeJSWorld().execute(
{"operation": "validate", "world_spec": spec, "duration_seconds": 12}
)
assert not result.success
assert "Last camera key" in (result.error or "")
def test_production_tier_rejects_primitive_only_spec():
result = ThreeJSWorld().execute({
"operation": "validate",
"world_spec": _world_spec(),
"duration_seconds": 12,
"quality_tier": "production",
"asset_catalog_paths": [],
})
assert not result.success
assert "asset catalog" in (result.error or "").lower()
assert "asset-palette" in (result.error or "").lower()
assert "terrain material" in (result.error or "").lower()
def test_blockout_tier_is_labeled_as_nonproduction():
result = ThreeJSWorld().execute({
"operation": "validate",
"world_spec": _world_spec(),
"duration_seconds": 12,
"quality_tier": "blockout",
})
assert result.success
assert result.data["report"]["quality_tier"] == "blockout"
assert any("do not present" in warning.lower() for warning in result.data["report"]["warnings"])
def test_hyperframes_render_existing_preserves_authored_entry(tmp_path, monkeypatch):
workspace = tmp_path / "world"
workspace.mkdir()
entry = workspace / "index.html"
entry.write_text("<main data-composition-id='world'></main>", encoding="utf-8")
tool = HyperFramesCompose()
monkeypatch.setattr(tool, "_runtime_check", lambda: {"runtime_available": True})
monkeypatch.setattr(tool, "_check", lambda inputs: ToolResult(success=True, data={"ok": True}))
def fake_run(args, *, cwd, timeout, check):
output = Path(args[args.index("--output") + 1])
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(b"rendered")
return subprocess.CompletedProcess(args, 0, "", "")
monkeypatch.setattr(tool, "_run_hf", fake_run)
output = tmp_path / "renders" / "final.mp4"
result = tool.execute(
{
"operation": "render_existing",
"workspace_path": str(workspace),
"output_path": str(output),
"quality": "draft",
}
)
assert result.success, result.error
assert result.data["authored_entry_preserved"] is True
assert entry.read_text(encoding="utf-8") == "<main data-composition-id='world'></main>"
assert output.is_file()
def test_video_compose_routes_empty_cut_atelier_to_existing_workspace(tmp_path, monkeypatch):
captured = {}
output = tmp_path / "final.mp4"
def fake_hyperframes_execute(self, inputs):
captured.update(inputs)
Path(inputs["output_path"]).write_bytes(b"fake mp4")
return ToolResult(success=True, data={"output": inputs["output_path"]})
monkeypatch.setattr(VideoCompose, "_hyperframes_available", lambda self: True)
monkeypatch.setattr(HyperFramesCompose, "execute", fake_hyperframes_execute)
monkeypatch.setattr(
VideoCompose,
"_run_final_review",
lambda self, *args, **kwargs: {"status": "pass", "issues_found": []},
)
result = VideoCompose().execute(
{
"operation": "render",
"workspace_path": str(tmp_path / "world"),
"output_path": str(output),
"edit_decisions": {
"version": "1.0",
"cuts": [],
"render_runtime": "hyperframes",
"renderer_family": "bespoke",
"composition_mode": "atelier",
"bespoke": {"entry": "index.html"},
},
}
)
assert result.success, result.error
assert captured["operation"] == "render_existing"
assert captured["asset_manifest"] == {"version": "1.0", "assets": []}
assert captured["edit_decisions"]["cuts"] == []

View File

@@ -0,0 +1,83 @@
import sys
from types import SimpleNamespace
from tools.analysis.transcriber import Transcriber
class _Info:
language = "en"
duration = 1.0
def test_transcriber_uses_ctranslate2_cuda_without_torch(monkeypatch, tmp_path) -> None:
devices = []
class FakeWhisperModel:
def __init__(self, model_size, *, device, compute_type):
devices.append((device, compute_type))
def transcribe(self, *args, **kwargs):
return iter(()), _Info()
monkeypatch.setitem(
sys.modules,
"faster_whisper",
SimpleNamespace(WhisperModel=FakeWhisperModel),
)
monkeypatch.setitem(
sys.modules,
"ctranslate2",
SimpleNamespace(
get_cuda_device_count=lambda: 1,
get_supported_compute_types=lambda device: {"float16", "float32"},
),
)
input_path = tmp_path / "audio.wav"
input_path.write_bytes(b"fake")
result = Transcriber().execute({"input_path": str(input_path), "output_dir": str(tmp_path)})
assert result.success, result.error
assert devices == [("cuda", "float16")]
assert result.data["device"] == "cuda"
def test_transcriber_falls_back_when_cuda_fails_during_iteration(monkeypatch, tmp_path) -> None:
devices = []
class FakeWhisperModel:
def __init__(self, model_size, *, device, compute_type):
self.device = device
devices.append((device, compute_type))
def transcribe(self, *args, **kwargs):
if self.device == "cuda":
def broken_iterator():
raise RuntimeError("cublas64_12.dll not found")
yield
return broken_iterator(), _Info()
return iter(()), _Info()
monkeypatch.setitem(
sys.modules,
"faster_whisper",
SimpleNamespace(WhisperModel=FakeWhisperModel),
)
monkeypatch.setitem(
sys.modules,
"ctranslate2",
SimpleNamespace(
get_cuda_device_count=lambda: 1,
get_supported_compute_types=lambda device: {"float16"},
),
)
input_path = tmp_path / "audio.wav"
input_path.write_bytes(b"fake")
result = Transcriber().execute({"input_path": str(input_path), "output_dir": str(tmp_path)})
assert result.success, result.error
assert devices == [("cuda", "float16"), ("cpu", "int8")]
assert result.data["device"] == "cpu"
assert "cublas64_12.dll" in result.data["gpu_fallback_reason"]