app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
tools: wiki-issue-monitor.sh — the wiki-issue-loop live Monitor (John: 'do a monitor every 5 mins today'). Seeds on the current unread set so it cannot fire a 387-notification firehose, treats a failed poll as neither an event nor fatal, and marks items on repos this thread maintains.
1 file changed
+73
tools/wiki-issue-monitor.shadded+73@@ -0,0 +1,73 @@+#!/usr/bin/env bash+# wiki-issue-monitor.sh — poll the wiki notification feed and emit ONE LINE PER NEW ITEM.+#+# John, 2026-08-21: "do a monitor every 5 mins today to see if wiki issues are given to you."+# This is the `wiki-issue-loop` skill's option 2 (the live Monitor) — the one that makes same-hour+# issue ping-pong work, instead of waiting up to 30 min for the UserPromptSubmit nudge hook.+#+# TWO THINGS THIS GETS RIGHT, both of which are easy to get wrong:+# 1. It SEEDS on the current unread set. The feed had 387 unread when this was written; emitting+# those would be a 387-notification firehose and the monitor would be auto-stopped for volume.+# Only items that appear AFTER the seed are events.+# 2. A failed poll is never fatal and never an event. curl/parse failures leave the seen-set+# untouched and the loop continues, so one blip cannot kill the watch or fake an event.+#+# Output is deliberately narrow: one line per new notification, marked [MINE] when it lands on a repo+# this thread maintains, because those are the ones that change what I do next.+set -u+KEY_FILE="/var/run/adom/api-key"+INTERVAL="${WIM_INTERVAL:-300}"+MINE_RE="${WIM_MINE:-pup-bridge}"+SEEN="${TMPDIR:-/tmp}/.wiki-issue-monitor-seen"++[ -r "$KEY_FILE" ] || { echo "wiki-monitor: no api key at $KEY_FILE — cannot watch"; exit 1; }++fetch() {+ curl -s --max-time 20 -H "Authorization: Bearer $(cat "$KEY_FILE")" \+ "https://wiki.adom.inc/api/me/notifications?unread=1&limit=100" 2>/dev/null || true+}++# ── seed: everything already unread is history, not an event ────────────────────────────────────+fetch | python3 -c '+import sys,json+try: d=json.load(sys.stdin)+except Exception: sys.exit(0)+for n in (d.get("notifications") or []):+ print(n.get("id"))+' > "$SEEN" 2>/dev/null || true+echo "wiki-monitor: armed — $(wc -l < "$SEEN" 2>/dev/null || echo 0) existing unread seeded as history; polling every ${INTERVAL}s for NEW items only"++while true; do+ sleep "$INTERVAL"+ fetch | python3 -c '+import sys,json,os,re+seen_path=os.environ["SEEN"]; mine=re.compile(os.environ.get("MINE_RE","pup-bridge"))+try: d=json.load(sys.stdin)+except Exception: sys.exit(0) # bad/empty response: not an event, not a failure+items=d.get("notifications")+if items is None: sys.exit(0)+try: seen=set(x.strip() for x in open(seen_path) if x.strip())+except Exception: seen=set()+fresh=[]+for n in items:+ i=str(n.get("id") or "")+ if not i or i in seen: continue+ fresh.append(n); seen.add(i)+for n in fresh:+ # Field names verified against a live payload (2026-08-21): ref / actor / type / title /+ # reason / issue_status. Guessing these produced "? — update by someone" on the first run.+ ref=str(n.get("ref") or "?")+ who=n.get("actor") or "someone"+ ev=(n.get("type") or "update").replace("_"," ")+ st=n.get("issue_status") or ""+ why=n.get("reason") or ""+ title=re.sub(r"\s+"," ",str(n.get("title") or ""))[:80]+ tag="[MINE] " if mine.search(ref) else ""+ extra=" ".join(x for x in (f"({st})" if st else "", f"[{why}]" if why else "") if x)+ print(f"{tag}wiki: {ref} — {ev} by {who} {extra}: \"{title}\"", flush=True)+if fresh:+ try:+ with open(seen_path,"w") as f: f.write("\n".join(sorted(seen))+"\n")+ except Exception: pass+' SEEN="$SEEN" MINE_RE="$MINE_RE" 2>/dev/null || true+done