(self, args: Dict[str, Any])
| 319 | ) |
| 320 | |
| 321 | async def _remove_background(self, args: Dict[str, Any]) -> ToolExecutionResult: |
| 322 | replicate_api_key = self._effective_replicate_api_key() |
| 323 | if not replicate_api_key: |
| 324 | return ToolExecutionResult( |
| 325 | ok=False, |
| 326 | result={"error": "Background removal requires REPLICATE_API_KEY."}, |
| 327 | summary={"error": "Missing Replicate API key"}, |
| 328 | ) |
| 329 | |
| 330 | image_urls = args.get("image_urls") or [] |
| 331 | if not isinstance(image_urls, list) or not image_urls: |
| 332 | return ToolExecutionResult( |
| 333 | ok=False, |
| 334 | result={ |
| 335 | "error": "remove_background requires a non-empty image_urls list" |
| 336 | }, |
| 337 | summary={"error": "Missing image_urls"}, |
| 338 | ) |
| 339 | |
| 340 | cleaned = [url.strip() for url in image_urls if isinstance(url, str)] |
| 341 | unique_urls = list(dict.fromkeys([u for u in cleaned if u])) |
| 342 | if not unique_urls: |
| 343 | return ToolExecutionResult( |
| 344 | ok=False, |
| 345 | result={"error": "No valid image URLs provided"}, |
| 346 | summary={"error": "No valid image_urls"}, |
| 347 | ) |
| 348 | |
| 349 | batch_size = 20 |
| 350 | raw_results: list[str | BaseException] = [] |
| 351 | for i in range(0, len(unique_urls), batch_size): |
| 352 | batch = unique_urls[i : i + batch_size] |
| 353 | # Replicate can't fetch localhost; inline local assets as data URLs. |
| 354 | tasks = [ |
| 355 | remove_background(local_asset_url_to_data_url(url), replicate_api_key) |
| 356 | for url in batch |
| 357 | ] |
| 358 | raw_results.extend(await asyncio.gather(*tasks, return_exceptions=True)) |
| 359 | |
| 360 | results: List[Dict[str, Any]] = [] |
| 361 | for url, raw in zip(unique_urls, raw_results): |
| 362 | if isinstance(raw, BaseException): |
| 363 | print(f"Background removal failed for {url}: {raw}") |
| 364 | results.append( |
| 365 | {"image_url": url, "result_url": None, "status": "error"} |
| 366 | ) |
| 367 | else: |
| 368 | results.append( |
| 369 | {"image_url": url, "result_url": raw, "status": "ok"} |
| 370 | ) |
| 371 | |
| 372 | summary_items = [ |
| 373 | { |
| 374 | "image_url": summarize_text(r["image_url"], 100), |
| 375 | "result_url": r["result_url"], |
| 376 | "status": r["status"], |
| 377 | } |
| 378 | for r in results |
no test coverage detected