fix(open3dmodel): unwrap {success,data,error} envelope from /api/recipes

Open3DModel returns the same envelope for /api/recipes as for /api/pose;
the bare-list code path stays as a fallback for older mocks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal PastroandClaude Opus 4.7 committed 2026-05-13 10:17:48 +02:00
1 parent 33d66019ee
commit cb940dc1cd
2 files changed
+30 -4

No files matched your search

+18 -4
View File
@@ -59,10 +59,24 @@ class Open3DModelClient:
body = r.json()
except ValueError as e:
raise Open3DModelUnavailable(f"non-JSON response: {e}") from e
if not isinstance(body, list):
raise Open3DModelError("UNEXPECTED_PAYLOAD",
f"expected list, got {type(body).__name__}")
return body
# Open3DModel wraps list responses in the {success, data, error} envelope
# too; older mocks may return a bare list. Accept either shape.
if isinstance(body, dict) and "success" in body:
if not body.get("success"):
err = body.get("error") or {}
raise Open3DModelError(
str(err.get("code") or "UNKNOWN"),
str(err.get("message") or "no message"),
)
data = body.get("data")
if not isinstance(data, list):
raise Open3DModelError("UNEXPECTED_PAYLOAD",
f"expected list in data, got {type(data).__name__}")
return data
if isinstance(body, list):
return body
raise Open3DModelError("UNEXPECTED_PAYLOAD",
f"expected list or envelope, got {type(body).__name__}")
def estimate_pose(self, recipe_id: str, points_cv_m: np.ndarray,
intrinsics: dict[str, Any]) -> dict[str, Any]: