Skip to content

Commit 918d895

Browse files
JihaoXinclaude
andcommitted
Convert deep research report to PDF before sending via Telegram
- _send_deep_research_telegram now converts md → PDF using markdown + weasyprint - Styled HTML intermediate: clean sans-serif, syntax highlighting, tables, toc - Falls back to .md file if PDF conversion fails (missing deps, etc.) - Falls back to raw text (4000 chars) if document upload fails Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b7998b1 commit 918d895

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

ark/orchestrator.py

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,65 @@ def _on_error(error_msg):
223223
)
224224

225225
def _send_deep_research_telegram(self, report_path: str):
226-
"""Send deep research completion notification and full report file to Telegram."""
226+
"""Send deep research report as PDF to Telegram (with md fallback)."""
227227
if not self.telegram.is_configured:
228228
return
229229
try:
230230
self.telegram.send("Deep Research completed!")
231-
ok = self.telegram.send_document(report_path, caption="📄 Full Deep Research report")
231+
# Convert markdown to PDF for better readability
232+
pdf_path = self._convert_md_to_pdf(report_path)
233+
if pdf_path:
234+
ok = self.telegram.send_document(pdf_path, caption="📄 Deep Research Report (PDF)")
235+
if ok:
236+
return
237+
# Fallback: send the .md file
238+
ok = self.telegram.send_document(report_path, caption="📄 Deep Research report (Markdown)")
232239
if not ok:
233-
# Fallback: send as text if document upload fails
234240
content = Path(report_path).read_text()
235241
self.telegram.send_raw(content[:4000])
236242
except Exception as e:
237243
self.log(f"Failed to send deep research to Telegram: {e}", "WARN")
238244

245+
def _convert_md_to_pdf(self, md_path: str) -> str:
246+
"""Convert a markdown file to PDF. Returns PDF path or empty string on failure."""
247+
try:
248+
import markdown
249+
from weasyprint import HTML
250+
251+
md_content = Path(md_path).read_text()
252+
html_body = markdown.markdown(
253+
md_content,
254+
extensions=["tables", "fenced_code", "codehilite", "toc"],
255+
)
256+
257+
# Wrap in styled HTML
258+
html_full = f"""<!DOCTYPE html>
259+
<html><head><meta charset="utf-8">
260+
<style>
261+
body {{ font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11pt;
262+
line-height: 1.6; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #333; }}
263+
h1 {{ font-size: 20pt; color: #1a1a2e; border-bottom: 2px solid #0d9488; padding-bottom: 8px; }}
264+
h2 {{ font-size: 15pt; color: #1a1a2e; margin-top: 24px; }}
265+
h3 {{ font-size: 12pt; color: #374151; }}
266+
code {{ background: #f3f4f6; padding: 2px 6px; border-radius: 4px; font-size: 10pt; }}
267+
pre {{ background: #f3f4f6; padding: 12px; border-radius: 8px; overflow-x: auto; font-size: 9pt; }}
268+
table {{ border-collapse: collapse; width: 100%; margin: 12px 0; }}
269+
th, td {{ border: 1px solid #d1d5db; padding: 8px 12px; text-align: left; font-size: 10pt; }}
270+
th {{ background: #f0fdfa; font-weight: 600; }}
271+
blockquote {{ border-left: 4px solid #0d9488; margin: 12px 0; padding: 8px 16px; color: #555; background: #f0fdfa; }}
272+
a {{ color: #0d9488; }}
273+
</style></head><body>{html_body}</body></html>"""
274+
275+
pdf_path = str(Path(md_path).with_suffix(".pdf"))
276+
HTML(string=html_full).write_pdf(pdf_path)
277+
self.log(f"Converted deep research to PDF: {pdf_path}", "INFO")
278+
return pdf_path
279+
except ImportError:
280+
self.log("markdown/weasyprint not installed, skipping PDF conversion", "WARN")
281+
except Exception as e:
282+
self.log(f"PDF conversion failed: {e}", "WARN")
283+
return ""
284+
239285
# ========== Telegram ==========
240286

241287
def _tg_history_append(self, role: str, text: str):

0 commit comments

Comments
 (0)