Skip to content

Commit 9eba441

Browse files
committed
fix: normalize MiniMax hex audio output
1 parent b5e5bc2 commit 9eba441

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

sdk/python/agentfield/media_providers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,12 @@ async def generate_music(self, prompt: str, model: Optional[str] = None, duratio
189189
if response.status >= 400 or data.get("base_resp", {}).get("status_code") != 0:
190190
raise RuntimeError(f"MiniMax music generation failed ({response.status}): {data}")
191191
audio = data.get("data", {}).get("audio")
192-
output = AudioOutput(data=audio if audio and body["output_format"] == "hex" else None, format=body.get("audio_setting", {}).get("format", "mp3"), url=audio if body["output_format"] == "url" else None)
192+
audio_data = (
193+
base64.b64encode(bytes.fromhex(audio)).decode("ascii")
194+
if audio and body["output_format"] == "hex"
195+
else None
196+
)
197+
output = AudioOutput(data=audio_data, format=body.get("audio_setting", {}).get("format", "mp3"), url=audio if body["output_format"] == "url" else None)
193198
return MultimodalResponse(text=prompt, audio=output, images=[], files=[], raw_response=data)
194199

195200

sdk/python/tests/test_media_providers.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from agentfield.media_providers import (
1919
FalProvider,
2020
LiteLLMProvider,
21+
MiniMaxProvider,
2122
OpenRouterProvider,
2223
MediaProvider,
2324
get_provider,
@@ -179,6 +180,68 @@ def test_fal_provider_parse_image_size_dimensions(self, fal_provider):
179180
result = fal_provider._parse_image_size("512x512")
180181
assert result == {"width": 512, "height": 512}
181182

183+
184+
class _MiniMaxResponse:
185+
def __init__(self, payload):
186+
self.status = 200
187+
self.payload = payload
188+
189+
async def __aenter__(self):
190+
return self
191+
192+
async def __aexit__(self, exc_type, exc, tb):
193+
return False
194+
195+
async def json(self):
196+
return self.payload
197+
198+
199+
class _MiniMaxSession:
200+
def __init__(self, payload):
201+
self.payload = payload
202+
self.request = None
203+
204+
async def __aenter__(self):
205+
return self
206+
207+
async def __aexit__(self, exc_type, exc, tb):
208+
return False
209+
210+
def post(self, endpoint, **kwargs):
211+
self.request = (endpoint, kwargs)
212+
return _MiniMaxResponse(self.payload)
213+
214+
215+
class TestMiniMaxProvider:
216+
@pytest.mark.asyncio
217+
async def test_generate_music_url_output(self):
218+
session = _MiniMaxSession(
219+
{"base_resp": {"status_code": 0}, "data": {"audio": "https://example.test/music.mp3"}}
220+
)
221+
provider = MiniMaxProvider(api_key="test-key")
222+
223+
with patch("aiohttp.ClientSession", return_value=session):
224+
result = await provider.generate_music("ambient piano", output_format="url")
225+
226+
assert result.audio.url == "https://example.test/music.mp3"
227+
assert result.audio.data is None
228+
assert session.request[1]["json"]["output_format"] == "url"
229+
230+
@pytest.mark.asyncio
231+
async def test_generate_music_hex_output_uses_audiooutput_base64_contract(self):
232+
audio_bytes = b"minimax-music"
233+
session = _MiniMaxSession(
234+
{"base_resp": {"status_code": 0}, "data": {"audio": audio_bytes.hex()}}
235+
)
236+
provider = MiniMaxProvider(api_key="test-key")
237+
238+
with patch("aiohttp.ClientSession", return_value=session):
239+
result = await provider.generate_music("ambient piano", output_format="hex")
240+
241+
assert result.audio.url is None
242+
assert result.audio.get_bytes() == audio_bytes
243+
assert session.request[1]["json"]["output_format"] == "hex"
244+
182245
def test_fal_provider_parse_image_size_invalid_fallback(self, fal_provider):
183246
"""FalProvider should fallback to square_hd for invalid sizes."""
184247
assert fal_provider._parse_image_size("invalid") == "square_hd"

0 commit comments

Comments
 (0)