Files
workspace/tools/people.py

152 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
people - Personal CRM / people notes
Keep notes about people you know.
"""
import json
import sys
from datetime import datetime
from pathlib import Path
WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
PEOPLE_FILE = WORKSPACE / "data" / "people.json"
def load_people() -> dict:
"""Load people data."""
PEOPLE_FILE.parent.mkdir(parents=True, exist_ok=True)
if PEOPLE_FILE.exists():
with open(PEOPLE_FILE) as f:
return json.load(f)
return {}
def save_people(data: dict):
"""Save people data."""
with open(PEOPLE_FILE, 'w') as f:
json.dump(data, f, indent=2)
def add_person(name: str, context: str = None):
"""Add a new person."""
people = load_people()
key = name.lower().replace(' ', '_')
if key in people:
print(f"Person already exists: {name}")
return
people[key] = {
'name': name,
'context': context,
'added': datetime.now().isoformat(),
'notes': [],
'tags': [],
'last_contact': None,
}
save_people(people)
print(f"👤 Added: {name}")
def add_note(name: str, note: str):
"""Add a note about someone."""
people = load_people()
search = name.lower().replace(' ', '')
# Find by partial match (normalize spaces)
matches = [k for k in people if search in k.replace('_', '') or search in people[k]['name'].lower().replace(' ', '')]
if not matches:
print(f"Person not found: {name}")
return
key = matches[0]
people[key]['notes'].append({
'text': note,
'date': datetime.now().isoformat(),
})
people[key]['last_contact'] = datetime.now().isoformat()
save_people(people)
print(f"📝 Note added for {people[key]['name']}")
def show_person(name: str):
"""Show info about a person."""
people = load_people()
search = name.lower().replace(' ', '')
# Find by partial match (normalize spaces)
matches = [k for k in people if search in k.replace('_', '') or search in people[k]['name'].lower().replace(' ', '')]
if not matches:
print(f"Person not found: {name}")
return
person = people[matches[0]]
print(f"\n👤 {person['name']}")
print("=" * 40)
if person.get('context'):
print(f"Context: {person['context']}")
if person.get('last_contact'):
last = person['last_contact'][:10]
print(f"Last contact: {last}")
if person['notes']:
print(f"\n📝 Notes ({len(person['notes'])})")
for note in person['notes'][-5:]:
date = note['date'][:10]
print(f" [{date}] {note['text'][:50]}")
print()
def list_people():
"""List all people."""
people = load_people()
if not people:
print("No people yet. Add with: people add <name>")
return
print(f"\n👥 People ({len(people)})")
print("=" * 40)
for key, person in sorted(people.items()):
notes = len(person['notes'])
context = person.get('context', '')[:20]
print(f" {person['name']:20} {notes} notes {context}")
print()
def main():
if len(sys.argv) < 2:
list_people()
return
cmd = sys.argv[1]
if cmd == 'add' and len(sys.argv) > 2:
name = sys.argv[2]
context = ' '.join(sys.argv[3:]) if len(sys.argv) > 3 else None
add_person(name, context)
elif cmd == 'note' and len(sys.argv) > 3:
name = sys.argv[2]
note = ' '.join(sys.argv[3:])
add_note(name, note)
elif cmd == 'show' and len(sys.argv) > 2:
show_person(sys.argv[2])
elif cmd == 'list':
list_people()
else:
print("Usage:")
print(" people - List all")
print(" people add <name> [context] - Add person")
print(" people note <name> <text> - Add note")
print(" people show <name> - Show person")
if __name__ == "__main__":
main()