Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "/output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return "", str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return "", str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
# Stage repo output.zip to runs//output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
# Stage repo output.zip to runs//output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
# Stage repo output.zip to runs//output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
# Stage repo output.zip to runs//output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_output_zip():
"""Compile the repo-root output.zip (a real LaTeX project) and preview the resulting PDF."""
# Stage repo output.zip to runs//output.zip to follow pipeline layout, then delegate
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
",
None,
)
logs = [f"🐞 Stage(repo zip) at {_now_str()}"]
_, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
try:
shutil.copy2(zip_path, ZIP_PATH)
logs.append(f"📦 Staged repo output.zip → runs/{WORK_DIR.name}/output.zip")
_write_logs(LOG_PATH, logs)
except Exception as e:
logs.append(f"❌ Failed staging output.zip: {e}")
_write_logs(LOG_PATH, logs)
return "Failed to stage output.zip
"
return debug_compile_last_pipeline_zip()
logs = [f"🐞 Debug(real) at {_now_str()}"]
zip_path = ROOT / "output.zip"
if not zip_path.exists():
return (
"output.zip not found at repo root.
"
+ f"Expected at: {zip_path}
"
)
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_proj"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append("Unzipping output.zip → zip_proj/")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(zip_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate poster_output.tex (fallback to poster.tex)
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
# fallback: any .tex
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in output.zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in output.zip
", None
# If left_logo missing, disable \logoleft
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in zip project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def _find_last_pipeline_zip():
try:
candidates = []
for d in RUNS_DIR.iterdir():
try:
if d.is_dir():
z = d / "output.zip"
if z.exists():
candidates.append((z.stat().st_mtime, z))
except Exception:
pass
if not candidates:
return None
candidates.sort(key=lambda x: x[0], reverse=True)
return candidates[0][1]
except Exception:
return None
def debug_compile_last_pipeline_zip():
"""Find the most recent runs/*/output.zip from pipeline, compile, and return preview HTML + PDF path."""
logs = [f"🐞 Debug(last-pipeline-zip) at {_now_str()}"]
last_zip = _find_last_pipeline_zip()
if not last_zip:
repo_zip = ROOT / "output.zip"
if repo_zip.exists():
try:
_, W, L, Z = _prepare_workspace(logs)
shutil.copy2(repo_zip, Z)
logs.append(f"📦 Auto-staged repo output.zip → runs/{W.name}/output.zip")
last_zip = Z
except Exception as e:
logs.append(f"❌ Auto-stage failed: {e}")
return "No recent pipeline output.zip found and auto-stage failed.
"
else:
return "No recent pipeline output.zip found under runs/.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_last"
work_zip_dir.mkdir(parents=True, exist_ok=True)
logs.append(f"Workspace: runs/{WORK_DIR.name}")
logs.append(f"Using: {last_zip}")
# Extract zip
try:
import zipfile as _zf
with _zf.ZipFile(last_zip, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Locate tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in last pipeline zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in last pipeline zip
", None
# Ensure local fonts and theme precedence (same as other debug path)
try:
src_fonts = ROOT / "template" / "fonts"
dst_fonts = work_zip_dir / "fonts"
if src_fonts.exists():
for root_dir, dirs, files in os.walk(src_fonts):
rel = Path(root_dir).relative_to(src_fonts)
out_dir = dst_fonts / rel
out_dir.mkdir(parents=True, exist_ok=True)
for fn in files:
if fn.lower().endswith((".ttf", ".otf")):
shutil.copy2(Path(root_dir)/fn, out_dir/fn)
logs.append("📁 Copied local fonts → zip_last/fonts/")
# Copy repository theme .sty next to tex and at root
try:
tmpl_dir = ROOT / "template"
for sty in tmpl_dir.glob("*.sty"):
shutil.copy2(sty, work_zip_dir / sty.name)
shutil.copy2(sty, tex_path.parent / sty.name)
logs.append("📄 Copied template/*.sty → zip_last/ and tex dir")
except Exception as e:
logs.append(f"⚠️ Copy sty failed: {e}")
except Exception as e:
logs.append(f"⚠️ Local font setup failed: {e}")
# Compile to PDF
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile last pipeline zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
def debug_compile_uploaded_zip(zip_file):
"""Compile an uploaded poster zip (user-provided); return preview HTML + PDF path."""
logs = [f"🐞 Debug(upload) at {_now_str()}"]
if not zip_file:
return "Please upload a .zip file first.
", None
# Prepare workspace
run_id, WORK_DIR, LOG_PATH, _ = _prepare_workspace(logs)
work_zip_dir = WORK_DIR / "zip_upload"
work_zip_dir.mkdir(parents=True, exist_ok=True)
# Save uploaded zip
up_path = work_zip_dir / "input.zip"
try:
shutil.copy(zip_file.name, up_path)
except Exception as e:
logs.append(f"❌ save upload failed: {e}")
_write_logs(LOG_PATH, logs)
return "Save upload failed.
", None
# Extract
try:
import zipfile as _zf
with _zf.ZipFile(up_path, 'r') as zf:
zf.extractall(work_zip_dir)
except Exception as e:
logs.append(f"❌ unzip failed: {e}")
_write_logs(LOG_PATH, logs)
return "Unzip failed.
", None
# Find tex
tex_path = None
for name in ("poster_output.tex", "poster.tex"):
cand = list(work_zip_dir.rglob(name))
if cand:
tex_path = cand[0]
break
if tex_path is None:
cand = list(work_zip_dir.rglob("*.tex"))
if cand:
tex_path = cand[0]
if tex_path is None:
logs.append("❌ No .tex file found in uploaded zip")
_write_logs(LOG_PATH, logs)
return "No .tex found in uploaded zip
"
# Disable logoleft if missing
try:
logos_dir = tex_path.parent / "logos"
has_left = False
if logos_dir.exists():
for p in logos_dir.iterdir():
if p.is_file() and p.stem == "left_logo":
has_left = True
break
if not has_left:
txt = tex_path.read_text(encoding="utf-8")
if "\\logoleft" in txt:
import re as _re
new_txt = _re.sub(r"^\\\s*logoleft\s*\{.*?\}\s*$", lambda m: "%" + m.group(0), txt, flags=_re.MULTILINE)
if new_txt != txt:
tex_path.write_text(new_txt, encoding="utf-8")
logs.append("ℹ️ No left_logo found; disabled \\logoleft in uploaded project.")
except Exception as e:
logs.append(f"⚠️ left_logo adjust failed: {e}")
# Compile
pdf_path = _compile_tex_to_pdf(tex_path, logs)
if not pdf_path or not pdf_path.exists():
logs.append("❌ Failed to compile uploaded zip PDF.")
_write_logs(LOG_PATH, logs)
return (
"Compile failed.
"
+ ""
+ "\n".join(logs)
+ "",
None,
)
try:
b64 = base64.b64encode(pdf_path.read_bytes()).decode("utf-8")
open_tab = f"Open PDF in new tab"
html = (
f"{open_tab}
"
+ _pdf_to_iframe_html(pdf_path, height="700px")
)
_write_logs(LOG_PATH, logs)
return html, str(pdf_path)
except Exception as e:
logs.append(f"⚠️ preview failed: {e}")
_write_logs(LOG_PATH, logs)
return f"Compiled but preview failed: {e}
", None
# =====================
# Gradio pipeline function (ISOLATED)
# =====================
def run_pipeline(arxiv_url, pdf_file, openai_key, logo_files, meeting_logo_file, theme_rgb):
_cleanup_old_runs(RETENTION_HOURS)
start_time = datetime.datetime.now()
logs = [f"🚀 Starting pipeline at {_now_str()}"]
# --- Prepare per-run workspace ---
run_id, WORK_DIR, LOG_PATH, ZIP_PATH = _prepare_workspace(logs)
INPUT_DIR = WORK_DIR / "input"
OUTPUT_DIR = WORK_DIR / "output"
LOGO_DIR = INPUT_DIR / "logo"
POSTER_LATEX_DIR = WORK_DIR / "posterbuilder" / "latex_proj"
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
# ====== Validation: must upload LOGO ======
if logo_files is None:
logo_files = []
if not isinstance(logo_files, (list, tuple)):
logo_files = [logo_files]
logo_files = [f for f in logo_files if f]
# if len(logo_files) == 0:
# msg = "❌ You must upload at least one institutional logo (multiple allowed)."
# logs.append(msg)
# _write_logs(LOG_PATH, logs)
# yield "\n".join(logs), "", None, ""
# return
# Save logos into run-local dir
for item in LOGO_DIR.iterdir():
if item.is_file():
item.unlink()
saved_logo_paths = []
for lf in logo_files:
p = LOGO_DIR / Path(lf.name).name
shutil.copy(lf.name, p)
saved_logo_paths.append(p)
logs.append(f"🏷️ Saved {len(saved_logo_paths)} logo file(s) → {LOGO_DIR.relative_to(WORK_DIR)}")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
# ====== Handle uploaded PDF (optional) ======
pdf_path = None
if pdf_file:
pdf_dir = INPUT_DIR / "pdf"
pdf_dir.mkdir(parents=True, exist_ok=True)
pdf_path = pdf_dir / Path(pdf_file.name).name
shutil.copy(pdf_file.name, pdf_path)
logs.append(f"📄 Uploaded PDF → {pdf_path.relative_to(WORK_DIR)}")
# For pipeline Step 1.5 compatibility: also copy to input/paper.pdf
canonical_pdf = INPUT_DIR / "paper.pdf"
shutil.copy(pdf_file.name, canonical_pdf)
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
# ====== Validate input source ======
if not arxiv_url and not pdf_file:
msg = "❌ Please provide either an arXiv link or upload a PDF file (choose one)."
logs.append(msg)
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
# ====== Build command (run INSIDE workspace) ======
cmd = [
sys.executable, "pipeline.py",
"--model_name_t", "gpt-5",
"--model_name_v", "gpt-5",
"--result_dir", "output",
"--paper_latex_root", "input/latex_proj",
"--openai_key", openai_key,
"--gemini_key", "##",
"--logo_dir", str(LOGO_DIR) # run-local logo dir
]
if arxiv_url:
cmd += ["--arxiv_url", arxiv_url]
# (Keep pdf via input/paper.pdf; pipeline will read it if exists)
logs.append("\n======= REAL-TIME LOG =======")
logs.append(f"cwd = runs/{WORK_DIR.name}")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
# ====== Run with REAL-TIME streaming, inside workspace ======
try:
process = subprocess.Popen(
cmd,
cwd=str(WORK_DIR),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True,
)
except Exception as e:
msg = f"❌ Pipeline failed to start: {e}"
logs.append(msg)
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
last_yield = time.time()
try:
while True:
# Timeout guard
if (datetime.datetime.now() - start_time).total_seconds() > TIMEOUT_SECONDS:
logs.append("❌ Pipeline timed out (30 min limit). Killing process…")
try:
process.kill()
except Exception:
pass
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
line = process.stdout.readline()
if line:
print(line, end="") # echo to Space logs
logs.append(line.rstrip("\n"))
_write_logs(LOG_PATH, logs)
now = time.time()
if now - last_yield >= 0.3:
last_yield = now
yield "\n".join(logs), "", None, None, ""
elif process.poll() is not None:
break
else:
time.sleep(0.05)
return_code = process.wait()
logs.append(f"\nProcess finished with code {return_code}")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
if return_code != 0:
logs.append("❌ Process exited with non-zero status. See logs above.")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
except Exception as e:
logs.append(f"❌ Error during streaming: {e}")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
finally:
try:
if process.stdout:
process.stdout.close()
except Exception:
pass
# ====== Check output ======
has_output = False
try:
if OUTPUT_DIR.exists():
for _ in OUTPUT_DIR.iterdir():
has_output = True
break
except FileNotFoundError:
has_output = False
if not has_output:
msg = "❌ No output generated. Please check logs above."
logs.append(msg)
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
return
# ====== NEW: Post-processing (optional features) ======
# 1) Optional meeting logo replacement; if not provided, apply default NeurIPS
applied_logo = _apply_meeting_logo(OUTPUT_DIR, meeting_logo_file, logs)
if not applied_logo:
_ensure_right_logo_default(OUTPUT_DIR, logs)
# 2) Optional theme color update
rgb_tuple = _parse_rgb(theme_rgb)
if theme_rgb and not rgb_tuple:
logs.append(f"⚠️ Ignored Theme RGB input '{theme_rgb}': expected like '94,46,145'.")
applied_rgb = _apply_theme_rgb(OUTPUT_DIR, rgb_tuple, logs) if rgb_tuple else False
# 3) Optional institutional logo -> left_logo.
_apply_left_logo(OUTPUT_DIR, logo_files, logs)
_ensure_left_logo_or_disable(OUTPUT_DIR, logs)
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), "", None, None, ""
# ====== Compile PDF (for download + image preview) ======
pdf_html = ""
compiled_pdf_file = None
try:
pdf_path = _compile_poster_pdf(OUTPUT_DIR, logs)
if pdf_path and pdf_path.exists():
compiled_pdf_file = str(pdf_path)
logs.append("🖨️ PDF compiled (image preview available).")
except Exception as e:
logs.append(f"⚠️ PDF compile skipped: {e}")
# ====== Zip output (run-local) ======
try:
target_dir = OUTPUT_DIR / "poster_latex_proj"
if not target_dir.exists():
logs.append("❌ poster_latex_proj folder not found")
else:
with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(target_dir):
for file in files:
file_path = Path(root) / file
arcname = file_path.relative_to(target_dir) # only relative to subfolder
zipf.write(file_path, arcname=arcname)
logs.append(f"✅ Zipped poster_latex_proj → {ZIP_PATH.relative_to(WORK_DIR)}")
except Exception as e:
logs.append(f"❌ Failed to create zip: {e}")
# ====== Prepare Overleaf base64 payload (optional) ======
overleaf_zip_b64 = ""
try:
with open(ZIP_PATH, "rb") as f:
overleaf_zip_b64 = base64.b64encode(f.read()).decode("utf-8")
logs.append("🔗 Prepared Overleaf base64 payload")
except Exception as e:
logs.append(f"⚠️ Failed Overleaf payload: {e}")
end_time = datetime.datetime.now()
dur = (end_time - start_time).seconds
logs.append(f"🏁 Completed at {_now_str()} (Duration: {dur}s)")
logs.append(f"🆔 run_id = {WORK_DIR.name}")
_write_logs(LOG_PATH, logs)
yield "\n".join(logs), (
pdf_html
), (
compiled_pdf_file
), (
str(ZIP_PATH) if ZIP_PATH.exists() else None
), render_overleaf_button(overleaf_zip_b64)
def debug_compile():
# Minimal debug disabled to simplify UI.
return "Minimal debug disabled. Use 'Test repo output.zip' or 'Test last pipeline zip'.
"
# =====================
# Gradio UI
# =====================
with gr.Blocks(title="🎓 Paper2Poster") as iface:
# Title
gr.Markdown("# 🎓 Paper2Poster")
gr.Markdown("""
[Paper](https://arxiv.org/abs/2505.21497) | [GitHub](https://github.com/Paper2Poster/Paper2Poster) | [Project Page](https://paper2poster.github.io/)
**TL;DR:** Upload your paper and get an auto-generated poster.
Please be patient — each paper takes about 8–10 minutes to process.
This work, developed in collaboration with [TVG@Oxford](https://torrvision.com/index.html) and [UWaterloo](https://uwaterloo.ca/), has been accepted to [NeurIPS 2025 D&B](https://neurips.cc/). The framework builds upon 🐪 [CAMEL-ai](https://github.com/camel-ai/camel).
""")
# Top-right logos (camel, tvg, waterloo) if available
gr.HTML(_ui_header_logos_html())
# -------- Input box --------
with gr.Row():
# ========== LEFT: INPUT ==========
with gr.Column(scale=1):
with gr.Accordion("Input", open=True):
arxiv_in = gr.Textbox(label="📘 ArXiv URL (choose one)", placeholder="https://arxiv.org/abs/2505.xxxxx")
pdf_in = gr.File(label="📄 Upload PDF (choose one)")
key_in = gr.Textbox(label="🔑 OpenAI API Key", placeholder="sk-...", type="password")
inst_logo_in = gr.File(
label="🏷️ Institutional Logo (optional, multiple allowed)",
file_count="multiple",
file_types=["image"],
)
with gr.Row():
with gr.Column():
conf_logo_in = gr.File(
label="🧩 Optional: Conference Logo (defaults to NeurIPS logo)",
file_count="single",
file_types=["image"],
)
with gr.Column():
_conf_path = _default_conf_logo_path()
conf_preview = gr.Image(
value=str(_conf_path) if _conf_path else None,
label="Default conference logo preview",
interactive=False,
)
theme_in = gr.ColorPicker(label="🎨 Theme Color (optional)", value="#5E2E91")
run_btn = gr.Button("🚀 Run", variant="primary")
# ========== RIGHT: OUTPUT ==========
with gr.Column(scale=1):
with gr.Accordion("Output", open=True):
# Preview on top
img_out = gr.Image(label="🖼️ Poster (Image Preview)", interactive=False)
# Logs in the middle (keep compact height)
logs_out = gr.Textbox(label="🧾 Logs", lines=10, max_lines=20)
# Downloads at bottom
pdf_out = gr.HTML(label="📄 Poster (PDF Preview)", visible=False)
with gr.Row():
pdf_file_out = gr.File(label="📄 Download Poster (PDF)", interactive=False, visible=True)
zip_out = gr.File(label="📦 Download Results (.zip)", interactive=False, visible=True)
gr.Markdown("The ZIP can be uploaded to Overleaf and compiled with XeLaTeX.")
overleaf_out = gr.HTML(label="Open in Overleaf")
# Debug (hidden)
debug_zip_btn= gr.Button("🐞 Test repo output.zip", variant="secondary", visible=False)
debug_zip_out= gr.HTML(label="🐞 Real Output Preview", visible=False)
debug_zip_img= gr.Image(label="🐞 Real Output Image", interactive=False, visible=False)
debug_zip_pdfpath = gr.Textbox(visible=False)
debug_last_btn= gr.Button("🐞 Test last pipeline zip", variant="secondary", visible=False)
debug_last_out= gr.HTML(label="🐞 Last Pipeline Preview", visible=False)
debug_last_img= gr.Image(label="🐞 Last Output Image", interactive=False, visible=False)
debug_last_pdfpath = gr.Textbox(visible=False)
_run_evt = run_btn.click(
fn=run_pipeline,
inputs=[arxiv_in, pdf_in, key_in, inst_logo_in, conf_logo_in, theme_in],
outputs=[logs_out, pdf_out, pdf_file_out, zip_out, overleaf_out],
)
_run_evt.then(fn=preview_image_from_pdf, inputs=[pdf_file_out], outputs=[img_out])
_dz = debug_zip_btn.click(fn=debug_compile_output_zip, inputs=[], outputs=[debug_zip_out, debug_zip_pdfpath])
_dz.then(fn=preview_image_from_pdf, inputs=[debug_zip_pdfpath], outputs=[debug_zip_img])
_dl = debug_last_btn.click(fn=debug_compile_last_pipeline_zip, inputs=[], outputs=[debug_last_out, debug_last_pdfpath])
_dl.then(fn=preview_image_from_pdf, inputs=[debug_last_pdfpath], outputs=[debug_last_img])
if __name__ == "__main__":
iface.launch(server_name="0.0.0.0", server_port=7860)