Spaces:
Running
Running
Vesuvius Radar 1.1.1: retry cut-off downloads (Scrolls 7094614, PR #287)
Browse files- app.py +1 -1
- radar_mcp.py +1 -1
- scanner.py +20 -11
app.py
CHANGED
|
@@ -50,7 +50,7 @@ VECS_FILE = DATA_DIR / "vectors.npz"
|
|
| 50 |
COLLECT = os.environ.get("RADAR_COLLECT", "1") != "0" # tests set 0: no background collector
|
| 51 |
SEMANTIC = os.environ.get("RADAR_SEMANTIC", "1") != "0"
|
| 52 |
PUBLIC_URL = "https://sharpmeow-vesuvius-radar.hf.space"
|
| 53 |
-
VERSION = "1.1.
|
| 54 |
|
| 55 |
CFG = scanner.load_config()
|
| 56 |
SCORER = scanner.Scorer(CFG)
|
|
|
|
| 50 |
COLLECT = os.environ.get("RADAR_COLLECT", "1") != "0" # tests set 0: no background collector
|
| 51 |
SEMANTIC = os.environ.get("RADAR_SEMANTIC", "1") != "0"
|
| 52 |
PUBLIC_URL = "https://sharpmeow-vesuvius-radar.hf.space"
|
| 53 |
+
VERSION = "1.1.1"
|
| 54 |
|
| 55 |
CFG = scanner.load_config()
|
| 56 |
SCORER = scanner.Scorer(CFG)
|
radar_mcp.py
CHANGED
|
@@ -27,7 +27,7 @@ def bind(app_module):
|
|
| 27 |
|
| 28 |
router = APIRouter()
|
| 29 |
VERSIONS = ("2025-06-18", "2025-03-26", "2024-11-05")
|
| 30 |
-
SERVER = {"name": "vesuvius-radar", "title": "Vesuvius Radar", "version": "1.1.
|
| 31 |
INSTRUCTIONS = (
|
| 32 |
"Vesuvius Radar keeps collecting new work that could help read the Herculaneum scrolls (the Vesuvius Challenge): "
|
| 33 |
"papers from arXiv and journals, GitHub repositories with ScrollPrize/villa pull requests, issues and releases, "
|
|
|
|
| 27 |
|
| 28 |
router = APIRouter()
|
| 29 |
VERSIONS = ("2025-06-18", "2025-03-26", "2024-11-05")
|
| 30 |
+
SERVER = {"name": "vesuvius-radar", "title": "Vesuvius Radar", "version": "1.1.1"}
|
| 31 |
INSTRUCTIONS = (
|
| 32 |
"Vesuvius Radar keeps collecting new work that could help read the Herculaneum scrolls (the Vesuvius Challenge): "
|
| 33 |
"papers from arXiv and journals, GitHub repositories with ScrollPrize/villa pull requests, issues and releases, "
|
scanner.py
CHANGED
|
@@ -17,6 +17,7 @@ import datetime as dt
|
|
| 17 |
import email.utils
|
| 18 |
import hashlib
|
| 19 |
import html
|
|
|
|
| 20 |
import json
|
| 21 |
import math
|
| 22 |
import os
|
|
@@ -93,8 +94,8 @@ class Fetcher:
|
|
| 93 |
err = e
|
| 94 |
if e.code not in (429, 500, 502, 503, 504):
|
| 95 |
raise
|
| 96 |
-
except (urllib.error.URLError, TimeoutError, ConnectionError) as e:
|
| 97 |
-
err = e
|
| 98 |
time.sleep(2 * (i + 1))
|
| 99 |
raise err # type: ignore[misc]
|
| 100 |
|
|
@@ -550,6 +551,14 @@ def _gh_get(url):
|
|
| 550 |
return FETCH.json(url, {"Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}, etag=True)
|
| 551 |
|
| 552 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 553 |
# ---------------------------------------------------------------- GitHub: who made the latest update
|
| 554 |
|
| 555 |
SLACK_S = 120 # an update this close to an item's updated time is the one that moved it
|
|
@@ -615,8 +624,8 @@ def gh_updates(repo: str, since: dt.datetime, notes: list, pages: int = 3) -> tu
|
|
| 615 |
c["updated_at"] if edited else c["created_at"], text, c.get("html_url")))
|
| 616 |
if len(rows) < 100:
|
| 617 |
break
|
| 618 |
-
except
|
| 619 |
-
notes.append(f"{repo} {path}:
|
| 620 |
try:
|
| 621 |
calls += 1
|
| 622 |
for e in _gh_get(f"{base}/issues/events?per_page=100"):
|
|
@@ -628,8 +637,8 @@ def gh_updates(repo: str, since: dt.datetime, notes: list, pages: int = 3) -> tu
|
|
| 628 |
or (e.get("milestone") or {}).get("title") or "")
|
| 629 |
out.setdefault(n, []).append(_act(what, (e.get("actor") or {}).get("login"), e["created_at"], clean(text)[:200],
|
| 630 |
(e.get("issue") or {}).get("html_url")))
|
| 631 |
-
except
|
| 632 |
-
notes.append(f"{repo} issues/events:
|
| 633 |
return out, calls
|
| 634 |
|
| 635 |
|
|
@@ -735,8 +744,8 @@ def c_github(sc, ctx):
|
|
| 735 |
url=r["html_url"], date=t, text=(r.get("body") or "")[:1500], base=50,
|
| 736 |
base_label=f"{repo} release", core_terms=False, who=repo.split("/")[0],
|
| 737 |
topics_extra=["Scroll work"])
|
| 738 |
-
except
|
| 739 |
-
notes.append(f"{repo}:
|
| 740 |
# Who made each item's latest update, and what it said: the item's own author is only who opened it.
|
| 741 |
acts = {}
|
| 742 |
if prs or issues:
|
|
@@ -757,8 +766,8 @@ def c_github(sc, ctx):
|
|
| 757 |
try:
|
| 758 |
act = latest_update(acts.get(n, []) + gh_pr_latest(repo, n), p.get("created_at"), p.get("updated_at"))
|
| 759 |
lookups[key] = {"updated": p.get("updated_at"), "act": act}
|
| 760 |
-
except
|
| 761 |
-
notes.append(f"{repo} #{n} reviews and commits:
|
| 762 |
common = dict(url=p["html_url"], date=t, text=(p.get("body") or "")[:1500], core_terms=False,
|
| 763 |
title=f"{repo} #{n}: {p['title']}", who=p["user"]["login"], created=p.get("created_at"),
|
| 764 |
labels=[x["name"] for x in p.get("labels") or []][:6], topics_extra=["Scroll work"], activity=act)
|
|
@@ -983,7 +992,7 @@ def collect(source: str, since: dt.datetime, cfg: dict | None = None, scorer: Sc
|
|
| 983 |
prog(f"scoring {len(items)} items")
|
| 984 |
finish(items, scorer, sem, prog, head)
|
| 985 |
items = [i for i in items if i["rule"] >= cfg["keep_score"]]
|
| 986 |
-
bad = any(re.search(r"HTTP \d|Error|rate limited|skipped|timed out", n) for n in info["notes"])
|
| 987 |
row.update(state="partial" if bad else "ok", read=info["read"], kept=len(items), notes=info["notes"])
|
| 988 |
except Exception as e: # noqa: BLE001
|
| 989 |
items = []
|
|
|
|
| 17 |
import email.utils
|
| 18 |
import hashlib
|
| 19 |
import html
|
| 20 |
+
import http.client
|
| 21 |
import json
|
| 22 |
import math
|
| 23 |
import os
|
|
|
|
| 94 |
err = e
|
| 95 |
if e.code not in (429, 500, 502, 503, 504):
|
| 96 |
raise
|
| 97 |
+
except (urllib.error.URLError, http.client.HTTPException, TimeoutError, ConnectionError) as e:
|
| 98 |
+
err = e # a dropped or cut-off download (IncompleteRead) is tried again like a refused one
|
| 99 |
time.sleep(2 * (i + 1))
|
| 100 |
raise err # type: ignore[misc]
|
| 101 |
|
|
|
|
| 551 |
return FETCH.json(url, {"Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}, etag=True)
|
| 552 |
|
| 553 |
|
| 554 |
+
# A failed villa listing costs only its own items: the repository search results of the same check are kept.
|
| 555 |
+
GH_ERRORS = (urllib.error.URLError, http.client.HTTPException, TimeoutError, ConnectionError, ValueError)
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
def _why(e) -> str:
|
| 559 |
+
return f"HTTP {e.code}" if isinstance(e, urllib.error.HTTPError) else f"network error ({type(e).__name__})"
|
| 560 |
+
|
| 561 |
+
|
| 562 |
# ---------------------------------------------------------------- GitHub: who made the latest update
|
| 563 |
|
| 564 |
SLACK_S = 120 # an update this close to an item's updated time is the one that moved it
|
|
|
|
| 624 |
c["updated_at"] if edited else c["created_at"], text, c.get("html_url")))
|
| 625 |
if len(rows) < 100:
|
| 626 |
break
|
| 627 |
+
except GH_ERRORS as e:
|
| 628 |
+
notes.append(f"{repo} {path}: {_why(e)}")
|
| 629 |
try:
|
| 630 |
calls += 1
|
| 631 |
for e in _gh_get(f"{base}/issues/events?per_page=100"):
|
|
|
|
| 637 |
or (e.get("milestone") or {}).get("title") or "")
|
| 638 |
out.setdefault(n, []).append(_act(what, (e.get("actor") or {}).get("login"), e["created_at"], clean(text)[:200],
|
| 639 |
(e.get("issue") or {}).get("html_url")))
|
| 640 |
+
except GH_ERRORS as e:
|
| 641 |
+
notes.append(f"{repo} issues/events: {_why(e)}")
|
| 642 |
return out, calls
|
| 643 |
|
| 644 |
|
|
|
|
| 744 |
url=r["html_url"], date=t, text=(r.get("body") or "")[:1500], base=50,
|
| 745 |
base_label=f"{repo} release", core_terms=False, who=repo.split("/")[0],
|
| 746 |
topics_extra=["Scroll work"])
|
| 747 |
+
except GH_ERRORS as e:
|
| 748 |
+
notes.append(f"{repo}: {_why(e)}")
|
| 749 |
# Who made each item's latest update, and what it said: the item's own author is only who opened it.
|
| 750 |
acts = {}
|
| 751 |
if prs or issues:
|
|
|
|
| 766 |
try:
|
| 767 |
act = latest_update(acts.get(n, []) + gh_pr_latest(repo, n), p.get("created_at"), p.get("updated_at"))
|
| 768 |
lookups[key] = {"updated": p.get("updated_at"), "act": act}
|
| 769 |
+
except GH_ERRORS as e:
|
| 770 |
+
notes.append(f"{repo} #{n} reviews and commits: {_why(e)}")
|
| 771 |
common = dict(url=p["html_url"], date=t, text=(p.get("body") or "")[:1500], core_terms=False,
|
| 772 |
title=f"{repo} #{n}: {p['title']}", who=p["user"]["login"], created=p.get("created_at"),
|
| 773 |
labels=[x["name"] for x in p.get("labels") or []][:6], topics_extra=["Scroll work"], activity=act)
|
|
|
|
| 992 |
prog(f"scoring {len(items)} items")
|
| 993 |
finish(items, scorer, sem, prog, head)
|
| 994 |
items = [i for i in items if i["rule"] >= cfg["keep_score"]]
|
| 995 |
+
bad = any(re.search(r"HTTP \d|Error|rate limited|skipped|timed out|network error", n) for n in info["notes"])
|
| 996 |
row.update(state="partial" if bad else "ok", read=info["read"], kept=len(items), notes=info["notes"])
|
| 997 |
except Exception as e: # noqa: BLE001
|
| 998 |
items = []
|