Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
A comprehensive collection of Agent Skills for context engineering, multi-agent architectures, and production agent systems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
examples/digital-brain-skill/agents/scripts/stale_contacts.py
1#!/usr/bin/env python32"""3Stale Contacts Finder4Identifies contacts that haven't been reached out to recently.5"""67import json8from datetime import datetime, timedelta9from pathlib import Path1011BRAIN_ROOT = Path(__file__).parent.parent.parent1213# Thresholds by circle (in days)14THRESHOLDS = {15'inner': 14, # 2 weeks16'active': 30, # 1 month17'network': 60, # 2 months18'dormant': 180 # 6 months (for potential reactivation)19}2021def load_jsonl(filepath):22"""Load JSONL file, skipping schema lines."""23items = []24if not filepath.exists():25return items26with open(filepath, 'r') as f:27for line in f:28line = line.strip()29if not line:30continue31try:32data = json.loads(line)33if '_schema' not in data:34items.append(data)35except json.JSONDecodeError:36continue37return items3839def days_since(date_str):40"""Calculate days since a date string."""41if not date_str:42return 999 # Very stale if no date43try:44date = datetime.fromisoformat(date_str.replace('Z', '+00:00'))45return (datetime.now(date.tzinfo) - date).days46except (ValueError, TypeError):47return 9994849def find_stale_contacts():50"""Find contacts needing outreach."""51contacts = load_jsonl(BRAIN_ROOT / 'network' / 'contacts.jsonl')5253stale = {54'urgent': [], # Way overdue55'due': [], # Due for contact56'coming_up': [] # Getting close57}5859for contact in contacts:60circle = contact.get('circle', 'network')61threshold = THRESHOLDS.get(circle, 60)62days = days_since(contact.get('last_contact'))6364contact_info = {65'name': contact.get('name', 'Unknown'),66'circle': circle,67'days_since': days,68'threshold': threshold,69'handle': contact.get('handle', ''),70'notes': contact.get('notes', '')[:100]71}7273if days > threshold * 1.5:74stale['urgent'].append(contact_info)75elif days > threshold:76stale['due'].append(contact_info)77elif days > threshold * 0.75:78stale['coming_up'].append(contact_info)7980return stale8182def generate_report():83"""Generate stale contacts report."""84stale = find_stale_contacts()8586output = f"""87# Stale Contacts Report88Generated: {datetime.now().isoformat()}8990## Urgently Overdue ({len(stale['urgent'])})91"""9293if stale['urgent']:94for c in sorted(stale['urgent'], key=lambda x: -x['days_since']):95output += f"- **{c['name']}** ({c['circle']}) - {c['days_since']} days since contact\n"96if c['handle']:97output += f" {c['handle']}\n"98else:99output += "None! You're on top of things.\n"100101output += f"""102## Due for Contact ({len(stale['due'])})103"""104105if stale['due']:106for c in sorted(stale['due'], key=lambda x: -x['days_since']):107output += f"- {c['name']} ({c['circle']}) - {c['days_since']} days\n"108else:109output += "None due right now.\n"110111output += f"""112## Coming Up ({len(stale['coming_up'])})113"""114115if stale['coming_up']:116for c in sorted(stale['coming_up'], key=lambda x: -x['days_since']):117output += f"- {c['name']} ({c['circle']}) - {c['days_since']} days (threshold: {c['threshold']})\n"118else:119output += "No contacts approaching threshold.\n"120121output += """122## Suggested Actions1231241. Send a quick "thinking of you" message to urgent contacts1252. Schedule calls with due inner-circle contacts1263. Engage with content from coming-up contacts127128## Thresholds129130- Inner circle: Every 2 weeks131- Active: Every month132- Network: Every 2 months133- Dormant: Quarterly check for reactivation134"""135136return output137138if __name__ == '__main__':139print(generate_report())140