Files
timmy-home/uniwizard/kimi-mention-watcher.sh
Timmy Bot 9952ce180c feat(uniwizard): standardized Tailscale IP detection module (timmy-home#385)
Create reusable tailscale-gitea.sh module for all auxiliary scripts:
- Automatically detects Tailscale (100.126.61.75) vs public IP (143.198.27.163)
- Sets GITEA_BASE_URL and GITEA_USING_TAILSCALE for sourcing scripts
- Configurable timeout, debug mode, and endpoint settings
- Maintains sovereignty: prefers private Tailscale network

Updated scripts:
- kimi-heartbeat.sh: now sources the module
- kimi-mention-watcher.sh: added fallback support via module

Files added:
- uniwizard/lib/tailscale-gitea.sh (reusable module)
- uniwizard/lib/example-usage.sh (usage documentation)

Acceptance criteria:
✓ Reusable module created and sourceable
✓ kimi-heartbeat.sh updated
✓ kimi-mention-watcher.sh updated (added fallback support)
✓ Example usage script provided
2026-04-05 07:07:05 +00:00

88 lines
2.7 KiB
Bash
Executable File

#!/bin/bash
# kimi-mention-watcher.sh — Watches for @KimiClaw mentions in Gitea
# Polls notifications, finds unread mentions, dispatches response via OpenClaw
set -euo pipefail
KIMI_TOKEN=$(cat /Users/apayne/.timmy/kimi_gitea_token | tr -d '[:space:]')
# --- Tailscale/IP Detection (timmy-home#385) ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/tailscale-gitea.sh"
BASE="$GITEA_BASE_URL"
LOG="/tmp/kimi-mentions.log"
PROCESSED="/tmp/kimi-mentions-processed.txt"
touch "$PROCESSED"
log() { echo "[$(date '+%H:%M:%S')] $*" | tee -a "$LOG"; }
# Get unread notifications for KimiClaw
notifications=$(curl -s -H "Authorization: token $KIMI_TOKEN" \
"$BASE/notifications?status-types=unread&limit=20" 2>/dev/null)
if [ -z "$notifications" ] || [ "$notifications" = "null" ] || [ "$notifications" = "[]" ]; then
exit 0
fi
echo "$notifications" | python3 -c "
import json, sys
notifs = json.load(sys.stdin)
for n in notifs:
subject = n.get('subject', {})
repo = n.get('repository', {}).get('full_name', '')
title = subject.get('title', '')
url = subject.get('latest_comment_url', '') or subject.get('url', '')
nid = n.get('id', '')
print(f'{nid}|{repo}|{title}|{url}')
" 2>/dev/null | while IFS='|' read -r nid repo title url; do
[ -z "$nid" ] && continue
# Skip if already processed
grep -q "^$nid$" "$PROCESSED" && continue
log "MENTION: $repo$title"
# Get the actual comment content
if [ -n "$url" ]; then
comment_body=$(curl -s -H "Authorization: token $KIMI_TOKEN" "$url" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('body','')[:500])" 2>/dev/null)
else
comment_body="(no comment body available)"
fi
# Extract issue number from URL
issue_num=$(echo "$url" | grep -o '/issues/[0-9]*' | grep -o '[0-9]*' || echo "")
comment_id=$(echo "$url" | grep -o '/comments/[0-9]*' | grep -o '[0-9]*' || echo "")
# Dispatch to OpenClaw for response
prompt="You are KimiClaw, Timmy's apprentice on Gitea. Someone mentioned you.
CONTEXT:
Repo: $repo
Issue/PR: $title
Comment: $comment_body
YOUR TASK:
Respond helpfully to the mention. If they asked a question, answer it.
If they asked you to do something, do it or explain what you need.
Post your response as a comment on the issue.
Gitea API: $BASE, use token from /Users/apayne/.timmy/kimi_gitea_token
Repo: $repo, Issue: $issue_num"
openclaw agent --agent main --message "$prompt" > /dev/null 2>&1 &
# Mark notification as read
curl -s -X PATCH -H "Authorization: token $KIMI_TOKEN" \
"$BASE/notifications/threads/$nid" > /dev/null 2>&1
# Mark as processed
echo "$nid" >> "$PROCESSED"
log "DISPATCHED response for notification $nid"
done
log "Mention check complete."