Spaces:
Running
Running
KaiWu commited on
Commit ·
bfe7d22
1
Parent(s): 2aa101f
Add GLB preview extraction for Lux3D zip outputs
Browse files- agent_core/outputs.py +2 -0
- agent_core/tools/lux3d_tool.py +45 -0
agent_core/outputs.py
CHANGED
|
@@ -120,6 +120,7 @@ def write_lux3d_manifest(
|
|
| 120 |
image_path: Path,
|
| 121 |
requested_output_path: str,
|
| 122 |
output_path: Path | None,
|
|
|
|
| 123 |
busid: str | int | None,
|
| 124 |
status: int | None,
|
| 125 |
result_url: str | None,
|
|
@@ -136,6 +137,7 @@ def write_lux3d_manifest(
|
|
| 136 |
"image_path": workspace_relative(image_path),
|
| 137 |
"requested_output_path": requested_output_path,
|
| 138 |
"output_path": workspace_relative(output_path) if output_path else None,
|
|
|
|
| 139 |
"busid": busid,
|
| 140 |
"status": status,
|
| 141 |
"result_url": result_url,
|
|
|
|
| 120 |
image_path: Path,
|
| 121 |
requested_output_path: str,
|
| 122 |
output_path: Path | None,
|
| 123 |
+
preview_path: Path | None,
|
| 124 |
busid: str | int | None,
|
| 125 |
status: int | None,
|
| 126 |
result_url: str | None,
|
|
|
|
| 137 |
"image_path": workspace_relative(image_path),
|
| 138 |
"requested_output_path": requested_output_path,
|
| 139 |
"output_path": workspace_relative(output_path) if output_path else None,
|
| 140 |
+
"preview_path": workspace_relative(preview_path) if preview_path else None,
|
| 141 |
"busid": busid,
|
| 142 |
"status": status,
|
| 143 |
"result_url": result_url,
|
agent_core/tools/lux3d_tool.py
CHANGED
|
@@ -8,6 +8,7 @@ import time
|
|
| 8 |
import urllib.error
|
| 9 |
import urllib.parse
|
| 10 |
import urllib.request
|
|
|
|
| 11 |
from pathlib import Path
|
| 12 |
|
| 13 |
from agent_core.config import (
|
|
@@ -154,6 +155,45 @@ def download_lux3d_result(result_url: str, output_path: Path) -> None:
|
|
| 154 |
output_path.write_bytes(data)
|
| 155 |
|
| 156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
def run_generate_3d_model(
|
| 158 |
image_path: str,
|
| 159 |
output_path: str | None = None,
|
|
@@ -165,6 +205,7 @@ def run_generate_3d_model(
|
|
| 165 |
status = None
|
| 166 |
result_url = None
|
| 167 |
output = None
|
|
|
|
| 168 |
poll_count = 0
|
| 169 |
run_dir = None
|
| 170 |
run_id = None
|
|
@@ -213,6 +254,7 @@ def run_generate_3d_model(
|
|
| 213 |
output_name = requested_output_name or infer_lux3d_output_name(result_url)
|
| 214 |
output = run_dir / output_name
|
| 215 |
download_lux3d_result(result_url, output)
|
|
|
|
| 216 |
manifest_path = write_lux3d_manifest(
|
| 217 |
run_dir=run_dir,
|
| 218 |
run_id=run_id,
|
|
@@ -220,6 +262,7 @@ def run_generate_3d_model(
|
|
| 220 |
image_path=image,
|
| 221 |
requested_output_path=requested_output_path,
|
| 222 |
output_path=output,
|
|
|
|
| 223 |
busid=busid,
|
| 224 |
status=status,
|
| 225 |
result_url=result_url,
|
|
@@ -232,6 +275,7 @@ def run_generate_3d_model(
|
|
| 232 |
"run_id": run_id,
|
| 233 |
"run_dir": workspace_relative(run_dir),
|
| 234 |
"output_path": workspace_relative(output),
|
|
|
|
| 235 |
"manifest_path": workspace_relative(manifest_path),
|
| 236 |
"latest_path": workspace_relative(output_root / "latest"),
|
| 237 |
"busid": busid,
|
|
@@ -257,6 +301,7 @@ def run_generate_3d_model(
|
|
| 257 |
image_path=image,
|
| 258 |
requested_output_path=requested_output_path,
|
| 259 |
output_path=output,
|
|
|
|
| 260 |
busid=busid,
|
| 261 |
status=status,
|
| 262 |
result_url=result_url,
|
|
|
|
| 8 |
import urllib.error
|
| 9 |
import urllib.parse
|
| 10 |
import urllib.request
|
| 11 |
+
import zipfile
|
| 12 |
from pathlib import Path
|
| 13 |
|
| 14 |
from agent_core.config import (
|
|
|
|
| 155 |
output_path.write_bytes(data)
|
| 156 |
|
| 157 |
|
| 158 |
+
def safe_zip_target(extract_dir: Path, member_name: str) -> Path:
|
| 159 |
+
target = (extract_dir / member_name).resolve()
|
| 160 |
+
if not target.is_relative_to(extract_dir.resolve()):
|
| 161 |
+
raise RuntimeError(f"Unsafe path in Lux3D zip result: {member_name}")
|
| 162 |
+
return target
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
def extract_lux3d_glb_preview(zip_path: Path, run_dir: Path) -> Path:
|
| 166 |
+
extract_dir = run_dir / "extracted"
|
| 167 |
+
try:
|
| 168 |
+
with zipfile.ZipFile(zip_path) as archive:
|
| 169 |
+
glb_members = sorted(
|
| 170 |
+
(
|
| 171 |
+
item
|
| 172 |
+
for item in archive.infolist()
|
| 173 |
+
if not item.is_dir() and Path(item.filename).suffix.lower() == ".glb"
|
| 174 |
+
),
|
| 175 |
+
key=lambda item: item.filename,
|
| 176 |
+
)
|
| 177 |
+
if not glb_members:
|
| 178 |
+
raise RuntimeError(f"Lux3D zip result did not include a .glb file: {workspace_relative(zip_path)}")
|
| 179 |
+
|
| 180 |
+
member = glb_members[0]
|
| 181 |
+
preview_path = safe_zip_target(extract_dir, member.filename)
|
| 182 |
+
preview_path.parent.mkdir(parents=True, exist_ok=True)
|
| 183 |
+
preview_path.write_bytes(archive.read(member))
|
| 184 |
+
return preview_path
|
| 185 |
+
except zipfile.BadZipFile as exc:
|
| 186 |
+
raise RuntimeError(f"Lux3D result is not a valid zip file: {workspace_relative(zip_path)}") from exc
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
def resolve_lux3d_preview_path(output_path: Path, run_dir: Path) -> Path | None:
|
| 190 |
+
if zipfile.is_zipfile(output_path):
|
| 191 |
+
return extract_lux3d_glb_preview(output_path, run_dir)
|
| 192 |
+
if output_path.suffix.lower() == ".glb":
|
| 193 |
+
return output_path
|
| 194 |
+
return None
|
| 195 |
+
|
| 196 |
+
|
| 197 |
def run_generate_3d_model(
|
| 198 |
image_path: str,
|
| 199 |
output_path: str | None = None,
|
|
|
|
| 205 |
status = None
|
| 206 |
result_url = None
|
| 207 |
output = None
|
| 208 |
+
preview = None
|
| 209 |
poll_count = 0
|
| 210 |
run_dir = None
|
| 211 |
run_id = None
|
|
|
|
| 254 |
output_name = requested_output_name or infer_lux3d_output_name(result_url)
|
| 255 |
output = run_dir / output_name
|
| 256 |
download_lux3d_result(result_url, output)
|
| 257 |
+
preview = resolve_lux3d_preview_path(output, run_dir)
|
| 258 |
manifest_path = write_lux3d_manifest(
|
| 259 |
run_dir=run_dir,
|
| 260 |
run_id=run_id,
|
|
|
|
| 262 |
image_path=image,
|
| 263 |
requested_output_path=requested_output_path,
|
| 264 |
output_path=output,
|
| 265 |
+
preview_path=preview,
|
| 266 |
busid=busid,
|
| 267 |
status=status,
|
| 268 |
result_url=result_url,
|
|
|
|
| 275 |
"run_id": run_id,
|
| 276 |
"run_dir": workspace_relative(run_dir),
|
| 277 |
"output_path": workspace_relative(output),
|
| 278 |
+
"preview_path": workspace_relative(preview) if preview else None,
|
| 279 |
"manifest_path": workspace_relative(manifest_path),
|
| 280 |
"latest_path": workspace_relative(output_root / "latest"),
|
| 281 |
"busid": busid,
|
|
|
|
| 301 |
image_path=image,
|
| 302 |
requested_output_path=requested_output_path,
|
| 303 |
output_path=output,
|
| 304 |
+
preview_path=preview,
|
| 305 |
busid=busid,
|
| 306 |
status=status,
|
| 307 |
result_url=result_url,
|