IPF commited on
Commit
7bad154
Β·
verified Β·
1 Parent(s): dc824f5

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -13
app.py CHANGED
@@ -487,6 +487,10 @@ def is_final_answer(text: str) -> bool:
487
  # ============================================================
488
  def render_citations(text: str, browser: SimpleBrowser) -> str:
489
  """Convert citation markers to clickable HTML links with tooltips."""
 
 
 
 
490
  def replace_citation(m):
491
  cursor_str = m.group(1)
492
  full_match = m.group(0) # Get the full match to extract line info
@@ -527,7 +531,13 @@ def render_citations(text: str, browser: SimpleBrowser) -> str:
527
  # Create citation with tooltip (single line to avoid markdown conversion issues)
528
  tooltip_html = f'<span class="citation-tooltip"><div class="citation-tooltip-title">{title_display}</div>{line_html}<div class="citation-tooltip-snippet">{snippet_display}</div><div class="citation-tooltip-url">πŸ”— {html.escape(domain)}</div></span>'
529
 
530
- return f'<span class="citation-wrapper"><a href="{html.escape(url)}" target="_blank" class="citation-link">[{index}]</a>{tooltip_html}</span>'
 
 
 
 
 
 
531
 
532
  # Fallback if no URL
533
  return f'<span class="citation-link">[{index}]</span>'
@@ -536,23 +546,14 @@ def render_citations(text: str, browser: SimpleBrowser) -> str:
536
  pass
537
  return m.group(0)
538
 
539
- # First pass: replace citations with linked citations
540
  result = re.sub(r'[【\[](\d+)†.*?[】\]]', replace_citation, text)
541
 
542
  # Second pass: Remove standalone URLs that appear after text (common pattern)
543
  # This removes URLs that directly follow sentences without proper citation
544
  result = re.sub(r'(?<=[.!?])\s+(https?://[^\s]+)', '', result)
545
 
546
- # Third pass: Deduplicate adjacent identical citations
547
- # Matches: <span class="citation-wrapper">...</span> followed by optional whitespace and same wrapper
548
- while True:
549
- # Match citation wrapper and deduplicate
550
- new_result = re.sub(r'(<span class="citation-wrapper">.*?</span>)(\s*)\1', r'\1', result)
551
- if new_result == result:
552
- break
553
- result = new_result
554
-
555
- # Convert basic markdown to HTML
556
  result = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', result)
557
  result = re.sub(r'\*(.+?)\*', r'<em>\1</em>', result)
558
  result = re.sub(r'`(.+?)`', r'<code>\1</code>', result)
@@ -560,6 +561,17 @@ def render_citations(text: str, browser: SimpleBrowser) -> str:
560
  if not result.startswith('<p>'):
561
  result = f'<p>{result}</p>'
562
 
 
 
 
 
 
 
 
 
 
 
 
563
  return result
564
 
565
  def render_thinking_streaming(text: str) -> str:
@@ -1545,7 +1557,7 @@ def create_interface():
1545
  bottom: 125%;
1546
  left: 50%;
1547
  transform: translateX(-50%);
1548
- z-index: 9999;
1549
  width: 280px;
1550
  background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);
1551
  border: 2px solid #10a37f;
 
487
  # ============================================================
488
  def render_citations(text: str, browser: SimpleBrowser) -> str:
489
  """Convert citation markers to clickable HTML links with tooltips."""
490
+ # Store citation HTML to protect from markdown conversion
491
+ citation_store = {}
492
+ citation_counter = [0]
493
+
494
  def replace_citation(m):
495
  cursor_str = m.group(1)
496
  full_match = m.group(0) # Get the full match to extract line info
 
531
  # Create citation with tooltip (single line to avoid markdown conversion issues)
532
  tooltip_html = f'<span class="citation-tooltip"><div class="citation-tooltip-title">{title_display}</div>{line_html}<div class="citation-tooltip-snippet">{snippet_display}</div><div class="citation-tooltip-url">πŸ”— {html.escape(domain)}</div></span>'
533
 
534
+ citation_html = f'<span class="citation-wrapper"><a href="{html.escape(url)}" target="_blank" class="citation-link">[{index}]</a>{tooltip_html}</span>'
535
+
536
+ # Store citation HTML and return placeholder
537
+ placeholder = f'___CITATION_{citation_counter[0]}___'
538
+ citation_store[placeholder] = citation_html
539
+ citation_counter[0] += 1
540
+ return placeholder
541
 
542
  # Fallback if no URL
543
  return f'<span class="citation-link">[{index}]</span>'
 
546
  pass
547
  return m.group(0)
548
 
549
+ # First pass: replace citations with placeholders
550
  result = re.sub(r'[【\[](\d+)†.*?[】\]]', replace_citation, text)
551
 
552
  # Second pass: Remove standalone URLs that appear after text (common pattern)
553
  # This removes URLs that directly follow sentences without proper citation
554
  result = re.sub(r'(?<=[.!?])\s+(https?://[^\s]+)', '', result)
555
 
556
+ # Third pass: Convert basic markdown to HTML
 
 
 
 
 
 
 
 
 
557
  result = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', result)
558
  result = re.sub(r'\*(.+?)\*', r'<em>\1</em>', result)
559
  result = re.sub(r'`(.+?)`', r'<code>\1</code>', result)
 
561
  if not result.startswith('<p>'):
562
  result = f'<p>{result}</p>'
563
 
564
+ # Fourth pass: Restore citation HTML from placeholders
565
+ for placeholder, citation_html in citation_store.items():
566
+ result = result.replace(placeholder, citation_html)
567
+
568
+ # Fifth pass: Deduplicate adjacent identical citations
569
+ while True:
570
+ new_result = re.sub(r'(<span class="citation-wrapper">.*?</span>)(\s*)\1', r'\1', result)
571
+ if new_result == result:
572
+ break
573
+ result = new_result
574
+
575
  return result
576
 
577
  def render_thinking_streaming(text: str) -> str:
 
1557
  bottom: 125%;
1558
  left: 50%;
1559
  transform: translateX(-50%);
1560
+ z-index: 999999;
1561
  width: 280px;
1562
  background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);
1563
  border: 2px solid #10a37f;