nikeshn commited on
Commit
7259ade
Β·
verified Β·
1 Parent(s): b033a52

Update src/agentcore/scholarly.py

Browse files
Files changed (1) hide show
  1. src/agentcore/scholarly.py +60 -1
src/agentcore/scholarly.py CHANGED
@@ -16,7 +16,7 @@ from pydantic import BaseModel, ConfigDict, Field
16
 
17
  from src.config import get_settings, LIBBEE_VERSION
18
 
19
- from src.agentcore.utils import _strip_resource_noise
20
 
21
  logger = logging.getLogger(__name__)
22
 
@@ -237,3 +237,62 @@ async def enrich_papers_with_oa(papers: List[dict], max_lookups: int = 5) -> Lis
237
  if meta.get("venue") and not p.get("venue"):
238
  p["venue"] = meta["venue"]
239
  return papers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  from src.config import get_settings, LIBBEE_VERSION
18
 
19
+ from src.agentcore.utils import _escape, _strip_resource_noise
20
 
21
  logger = logging.getLogger(__name__)
22
 
 
237
  if meta.get("venue") and not p.get("venue"):
238
  p["venue"] = meta["venue"]
239
  return papers
240
+
241
+
242
+ # ── Shared evidence panel ────────────────────────────────────────────────────
243
+ # Used by BOTH search handlers (_run_search_mode and _research_snapshot) so the
244
+ # panel appears on ordinary searches, not only on "deep research" phrasing.
245
+ # Returns (papers, html). Never raises: on any failure returns ([], "") and the
246
+ # caller renders exactly its pre-3.8 output.
247
+
248
+ async def fetch_evidence_panel(topic: str, limit: int = 6, max_lookups: int = 5):
249
+ papers: List[dict] = []
250
+ try:
251
+ papers = await _openalex_search(topic, limit=limit)
252
+ if not papers:
253
+ papers = await _semantic_scholar_search(topic, limit=limit)
254
+ if papers:
255
+ papers = await enrich_papers_with_oa(papers, max_lookups=max_lookups)
256
+ except Exception as exc:
257
+ logger.warning(f"Evidence panel failed for '{topic}': {exc}")
258
+ return [], ""
259
+ if not papers:
260
+ return [], ""
261
+
262
+ rows = ""
263
+ for paper in papers[:5]:
264
+ _t = _escape(str(paper.get("title") or "Untitled"))
265
+ _y = _escape(str(paper.get("year") or "n.d."))
266
+ _v = _escape(str(paper.get("venue") or ""))
267
+ _c = paper.get("cited_by_count")
268
+ _link = paper.get("link") or (f"https://doi.org/{paper['doi']}" if paper.get("doi") else "")
269
+ _oa = paper.get("oa_pdf_url") or ""
270
+ _bits = [b for b in (_y, _v) if b]
271
+ if isinstance(_c, int) and _c > 0:
272
+ _bits.append(f"{_c:,} citations")
273
+ _meta = " \u00b7 ".join(_bits)
274
+ _title_html = (
275
+ f'<a href="{_escape(_link)}" target="_blank" style="color:#003366;font-weight:600">{_t}</a>'
276
+ if _link else f'<span style="font-weight:600">{_t}</span>'
277
+ )
278
+ _oa_html = (
279
+ f' \u00b7 <a href="{_escape(_oa)}" target="_blank" '
280
+ f'style="color:#047857;font-weight:700">\U0001f513 OA full text</a>'
281
+ if _oa else ""
282
+ )
283
+ rows += (
284
+ f'<div style="margin:7px 0;padding-left:2px;font-size:.84rem;line-height:1.55">'
285
+ f'{_title_html}<br>'
286
+ f'<span style="color:#6b7280;font-size:.78rem">{_meta}{_oa_html}</span></div>'
287
+ )
288
+ html = (
289
+ '<div style="margin-top:16px;padding:12px 14px;border:1px solid #d1fae5;'
290
+ 'border-radius:10px;background:#f0fdf9">'
291
+ '<div style="font-weight:700;color:#065f46;font-size:.86rem;margin-bottom:4px">'
292
+ '\U0001f50e Open scholarly evidence</div>'
293
+ '<div style="font-size:.76rem;color:#047857;margin-bottom:8px">'
294
+ 'Top open-index results (OpenAlex / Semantic Scholar) with legal open-access '
295
+ 'links via Unpaywall and metadata via Crossref where available.</div>'
296
+ f'{rows}</div>'
297
+ )
298
+ return papers, html