fix(design): use MuAPI result URL from creation response

This commit is contained in:
Anil-matcha 2026-09-01 15:13:29 +05:30
parent 36c879d974
commit 26f79bdfb6
4 changed files with 144 additions and 10 deletions

View File

@ -334,6 +334,31 @@ def _muapi_error(response):
return "MuAPI request failed"
def _muapi_result_url(response):
"""Return the documented result URL from the creation response."""
for item in _muapi_response_objects(response):
urls = item.get("urls")
if not isinstance(urls, dict) or "get" not in urls:
continue
result_url = urls.get("get")
if not isinstance(result_url, str) or not result_url:
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
)
try:
_validate_public_https_url(result_url)
except ValueError as exc:
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
) from exc
return result_url
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
)
def _muapi_output_url(response):
for item in _muapi_response_objects(response):
outputs = item.get("outputs")
@ -376,6 +401,7 @@ def _generate_with_muapi(prompt, output_path, aspect_ratio, api_key, model):
request_id = _muapi_response_value(response, ("request_id", "id"))
if not isinstance(request_id, str) or not request_id:
raise RuntimeError("MuAPI did not return a request ID")
result_url = _muapi_result_url(response)
data = response
for poll_number in range(MUAPI_MAX_POLLS + 1):
@ -397,7 +423,7 @@ def _generate_with_muapi(prompt, output_path, aspect_ratio, api_key, model):
time.sleep(MUAPI_POLL_INTERVAL)
data = _json_request(
f"{MUAPI_API_BASE}/predictions/{request_id}/result",
result_url,
api_key,
api_key_header="x-api-key",
)

View File

@ -136,7 +136,15 @@ class MuapiGenerationTests(unittest.TestCase):
self, json_request, sleep, download
):
json_request.side_effect = [
{"id": "req-123", "status": "created"},
{
"id": "req-123",
"status": "created",
"output": {
"urls": {
"get": "https://api.muapi.ai/api/v1/results/req-123"
}
},
},
{"id": "req-123", "status": "processing"},
{
"id": "req-123",
@ -164,12 +172,12 @@ class MuapiGenerationTests(unittest.TestCase):
json_request.call_args_list[1:],
[
call(
f"{logo_generate.MUAPI_API_BASE}/predictions/req-123/result",
"https://api.muapi.ai/api/v1/results/req-123",
"muapi-key",
api_key_header="x-api-key",
),
call(
f"{logo_generate.MUAPI_API_BASE}/predictions/req-123/result",
"https://api.muapi.ai/api/v1/results/req-123",
"muapi-key",
api_key_header="x-api-key",
),
@ -233,7 +241,14 @@ class MuapiGenerationTests(unittest.TestCase):
@patch.object(logo_generate, "_json_request")
def test_muapi_reports_failed_prediction(self, json_request):
json_request.side_effect = [
{"request_id": "req-123"},
{
"request_id": "req-123",
"output": {
"urls": {
"get": "https://api.muapi.ai/api/v1/results/req-123"
}
},
},
{"status": "failed", "error": "invalid prompt"},
]
@ -242,6 +257,32 @@ class MuapiGenerationTests(unittest.TestCase):
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
@patch.object(logo_generate, "_json_request")
def test_muapi_requires_creation_result_url(self, json_request):
json_request.return_value = {"request_id": "req-123", "status": "created"}
with self.assertRaisesRegex(RuntimeError, "valid HTTPS result URL"):
logo_generate._generate_with_muapi(
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
json_request.assert_called_once()
@patch.object(logo_generate, "_json_request")
def test_muapi_rejects_invalid_creation_result_url(self, json_request):
json_request.return_value = {
"request_id": "req-123",
"status": "created",
"output": {"urls": {"get": "http://api.muapi.ai/results/req-123"}},
}
with self.assertRaisesRegex(RuntimeError, "valid HTTPS result URL"):
logo_generate._generate_with_muapi(
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
json_request.assert_called_once()
if __name__ == "__main__":
unittest.main()

View File

@ -334,6 +334,31 @@ def _muapi_error(response):
return "MuAPI request failed"
def _muapi_result_url(response):
"""Return the documented result URL from the creation response."""
for item in _muapi_response_objects(response):
urls = item.get("urls")
if not isinstance(urls, dict) or "get" not in urls:
continue
result_url = urls.get("get")
if not isinstance(result_url, str) or not result_url:
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
)
try:
_validate_public_https_url(result_url)
except ValueError as exc:
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
) from exc
return result_url
raise RuntimeError(
"MuAPI creation response did not include a valid HTTPS result URL"
)
def _muapi_output_url(response):
for item in _muapi_response_objects(response):
outputs = item.get("outputs")
@ -376,6 +401,7 @@ def _generate_with_muapi(prompt, output_path, aspect_ratio, api_key, model):
request_id = _muapi_response_value(response, ("request_id", "id"))
if not isinstance(request_id, str) or not request_id:
raise RuntimeError("MuAPI did not return a request ID")
result_url = _muapi_result_url(response)
data = response
for poll_number in range(MUAPI_MAX_POLLS + 1):
@ -397,7 +423,7 @@ def _generate_with_muapi(prompt, output_path, aspect_ratio, api_key, model):
time.sleep(MUAPI_POLL_INTERVAL)
data = _json_request(
f"{MUAPI_API_BASE}/predictions/{request_id}/result",
result_url,
api_key,
api_key_header="x-api-key",
)

View File

@ -136,7 +136,15 @@ class MuapiGenerationTests(unittest.TestCase):
self, json_request, sleep, download
):
json_request.side_effect = [
{"id": "req-123", "status": "created"},
{
"id": "req-123",
"status": "created",
"output": {
"urls": {
"get": "https://api.muapi.ai/api/v1/results/req-123"
}
},
},
{"id": "req-123", "status": "processing"},
{
"id": "req-123",
@ -164,12 +172,12 @@ class MuapiGenerationTests(unittest.TestCase):
json_request.call_args_list[1:],
[
call(
f"{logo_generate.MUAPI_API_BASE}/predictions/req-123/result",
"https://api.muapi.ai/api/v1/results/req-123",
"muapi-key",
api_key_header="x-api-key",
),
call(
f"{logo_generate.MUAPI_API_BASE}/predictions/req-123/result",
"https://api.muapi.ai/api/v1/results/req-123",
"muapi-key",
api_key_header="x-api-key",
),
@ -233,7 +241,14 @@ class MuapiGenerationTests(unittest.TestCase):
@patch.object(logo_generate, "_json_request")
def test_muapi_reports_failed_prediction(self, json_request):
json_request.side_effect = [
{"request_id": "req-123"},
{
"request_id": "req-123",
"output": {
"urls": {
"get": "https://api.muapi.ai/api/v1/results/req-123"
}
},
},
{"status": "failed", "error": "invalid prompt"},
]
@ -242,6 +257,32 @@ class MuapiGenerationTests(unittest.TestCase):
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
@patch.object(logo_generate, "_json_request")
def test_muapi_requires_creation_result_url(self, json_request):
json_request.return_value = {"request_id": "req-123", "status": "created"}
with self.assertRaisesRegex(RuntimeError, "valid HTTPS result URL"):
logo_generate._generate_with_muapi(
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
json_request.assert_called_once()
@patch.object(logo_generate, "_json_request")
def test_muapi_rejects_invalid_creation_result_url(self, json_request):
json_request.return_value = {
"request_id": "req-123",
"status": "created",
"output": {"urls": {"get": "http://api.muapi.ai/results/req-123"}},
}
with self.assertRaisesRegex(RuntimeError, "valid HTTPS result URL"):
logo_generate._generate_with_muapi(
"logo prompt", "logo.png", "1:1", "muapi-key", "nano-banana"
)
json_request.assert_called_once()
if __name__ == "__main__":
unittest.main()