feat(video_gen): route FAL video gen through managed Nous gateway
Wire plugins/video_gen/fal/__init__.py to use the same _ManagedFalSyncClient pattern that image gen already uses. Changes: - Add managed gateway resolution, client caching, and _submit_fal_video_request() that routes between direct FAL_KEY and Nous gateway modes - Update is_available() to return True when either FAL_KEY or the managed gateway is reachable - Update generate() to use submit+get handle pattern instead of fal_client.subscribe() directly - Fix happy-horse endpoint namespace: fal-ai/ → alibaba/ (matches the tool-gateway allowlist from fal-video-gen branch) - Surface actionable error on 4xx gateway rejections Tests: - 4 new tests in test_managed_media_gateways.py (gateway routing, client reuse, direct mode fallback, alibaba namespace) - Updated existing test_fal_plugin.py fixture to use submit/handle pattern and patch _resolve_managed_fal_video_gateway for isolation
This commit is contained in:
committed by
Siddharth Balyan
parent
5cd0673217
commit
d04b3c193e
@@ -85,15 +85,21 @@ def test_fal_list_models_advertises_both_modalities():
|
||||
|
||||
def test_fal_unavailable_without_key(monkeypatch):
|
||||
from plugins.video_gen.fal import FALVideoGenProvider
|
||||
from plugins.video_gen import fal as fal_plugin
|
||||
|
||||
monkeypatch.delenv("FAL_KEY", raising=False)
|
||||
# Also ensure managed gateway is unavailable
|
||||
monkeypatch.setattr(fal_plugin, "_resolve_managed_fal_video_gateway", lambda: None)
|
||||
assert FALVideoGenProvider().is_available() is False
|
||||
|
||||
|
||||
def test_fal_generate_requires_fal_key(monkeypatch):
|
||||
from plugins.video_gen.fal import FALVideoGenProvider
|
||||
from plugins.video_gen import fal as fal_plugin
|
||||
|
||||
monkeypatch.delenv("FAL_KEY", raising=False)
|
||||
# Also ensure managed gateway is unavailable
|
||||
monkeypatch.setattr(fal_plugin, "_resolve_managed_fal_video_gateway", lambda: None)
|
||||
result = FALVideoGenProvider().generate("a happy dog")
|
||||
assert result["success"] is False
|
||||
assert result["error_type"] == "auth_required"
|
||||
@@ -104,25 +110,34 @@ class TestFamilyRouting:
|
||||
|
||||
@pytest.fixture
|
||||
def with_fake_fal(self, monkeypatch):
|
||||
"""Stub fal_client.subscribe to capture which endpoint we hit."""
|
||||
"""Stub fal_client.submit to capture which endpoint we hit."""
|
||||
import sys
|
||||
import types
|
||||
|
||||
captured = {"endpoint": None, "arguments": None}
|
||||
|
||||
class FakeHandle:
|
||||
def get(self):
|
||||
return {"video": {"url": "https://fake/out.mp4"}}
|
||||
|
||||
fake = types.ModuleType("fal_client")
|
||||
def _subscribe(endpoint, arguments=None, with_logs=False):
|
||||
def _submit(endpoint, arguments=None, headers=None):
|
||||
captured["endpoint"] = endpoint
|
||||
captured["arguments"] = arguments
|
||||
return {"video": {"url": "https://fake/out.mp4"}}
|
||||
fake.subscribe = _subscribe # type: ignore
|
||||
return FakeHandle()
|
||||
fake.submit = _submit # type: ignore
|
||||
monkeypatch.setitem(sys.modules, "fal_client", fake)
|
||||
|
||||
# Reset the lazy global so it picks up our stub
|
||||
from plugins.video_gen import fal as fal_plugin
|
||||
fal_plugin._fal_client = None
|
||||
# Also reset the managed client cache
|
||||
fal_plugin._managed_fal_video_client = None
|
||||
fal_plugin._managed_fal_video_client_config = None
|
||||
|
||||
monkeypatch.setenv("FAL_KEY", "test")
|
||||
# Force direct mode — no managed gateway
|
||||
monkeypatch.setattr(fal_plugin, "_resolve_managed_fal_video_gateway", lambda: None)
|
||||
return captured
|
||||
|
||||
def test_text_to_video_routes_to_text_endpoint(self, with_fake_fal):
|
||||
|
||||
Reference in New Issue
Block a user