add agent workspace

This commit is contained in:
2026-02-18 22:39:35 -08:00
commit e8389b8772
48 changed files with 3476 additions and 0 deletions

221
scripts/reminder_check.py Normal file
View File

@@ -0,0 +1,221 @@
#!/usr/bin/env python3
"""
Daily Reminder Checker
Reads reminders from markdown table, filters due items, sends notification
"""
import re
import os
from datetime import datetime, timedelta
from pathlib import Path
# Paths
BASE_DIR = Path.home() / ".openclaw/workspace/reminders"
ACTIVE_FILE = BASE_DIR / "active.md"
ARCHIVE_DIR = BASE_DIR / "archive"
# Priority mapping (lower number = higher priority)
PRIORITY_MAP = {
'': 0, 'urgent': 0, 'high': 0,
'': 1, 'normal': 1, 'medium': 1,
'': 2, 'low': 2
}
def parse_table(content):
"""Parse markdown table into list of dicts"""
lines = content.strip().split('\n')
reminders = []
for line in lines:
# Skip header lines and separators
if line.startswith('|') and '---' not in line and '事项' not in line:
cells = [cell.strip() for cell in line.split('|')[1:-1]]
if len(cells) >= 4 and cells[0] and cells[0] != '事项':
reminder = {
'事项': cells[0],
'截止日期': cells[1] if len(cells) > 1 else '',
'优先级': cells[2] if len(cells) > 2 else '',
'状态': cells[3] if len(cells) > 3 else 'pending',
'备注': cells[4] if len(cells) > 4 else ''
}
reminders.append(reminder)
return reminders
def get_default_date():
"""Return tomorrow's date as string"""
tomorrow = datetime.now() + timedelta(days=1)
return tomorrow.strftime('%Y-%m-%d')
def normalize_reminder(reminder):
"""Apply defaults and normalize"""
# Default priority
if not reminder['优先级']:
reminder['优先级'] = ''
# Default date
if not reminder['截止日期']:
reminder['截止日期'] = get_default_date()
# Normalize status
reminder['状态'] = reminder['状态'].lower() if reminder['状态'] else 'pending'
return reminder
def get_days_until(due_date_str):
"""Calculate days until due date"""
try:
due_date = datetime.strptime(due_date_str, '%Y-%m-%d')
today = datetime.now()
delta = (due_date.date() - today.date()).days
return delta
except ValueError:
return None
def get_urgency_label(days):
"""Get urgency label based on days until due"""
if days is None:
return "❓ 日期未知"
elif days < 0:
return f"🔴 逾期 {-days}"
elif days == 0:
return "🔴 今天"
elif days == 1:
return "🟡 明天"
elif days <= 3:
return f"🟡 {days} 天后"
else:
return f"🟢 {days} 天后"
def sort_reminders(reminders):
"""Sort by priority (high first), then by date (earlier first)"""
def sort_key(r):
priority = PRIORITY_MAP.get(r['优先级'].lower(), 1)
try:
date = datetime.strptime(r['截止日期'], '%Y-%m-%d')
except ValueError:
date = datetime.max
return (priority, date)
return sorted(reminders, key=sort_key)
def format_notification(pending_reminders):
"""Format all pending reminders for notification"""
if not pending_reminders:
return None
today_str = datetime.now().strftime('%Y-%m-%d')
lines = [f"📋 今日待办清单 ({today_str})", "=" * 50]
# Group by priority
groups = {'': [], '': [], '': []}
for r in pending_reminders:
prio = r['优先级']
if prio in groups:
groups[prio].append(r)
# Output high priority
if groups['']:
lines.append("\n🔴 高优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
# Output medium priority
if groups['']:
lines.append("\n🟡 中优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
# Output low priority
if groups['']:
lines.append("\n🟢 低优先级:")
for r in groups['']:
days = get_days_until(r['截止日期'])
urgency = get_urgency_label(days)
note = f" | {r['备注']}" if r['备注'] else ""
lines.append(f"{r['事项']} ({urgency}){note}")
lines.append("\n" + "=" * 50)
lines.append("📝 完成事项后请修改状态为 done")
lines.append("📁 管理文件: ~/.openclaw/workspace/reminders/active.md")
return '\n'.join(lines)
def archive_done_reminders(reminders):
"""Move done reminders to archive"""
done = [r for r in reminders if r['状态'] == 'done']
if not done:
return
# Create archive filename with current quarter
now = datetime.now()
quarter = (now.month - 1) // 3 + 1
archive_file = ARCHIVE_DIR / f"{now.year}-Q{quarter}.md"
# Append to archive
with open(archive_file, 'a', encoding='utf-8') as f:
for r in done:
f.write(f"| {r['事项']} | {r['截止日期']} | {r['优先级']} | done | {r['备注']} |\n")
def update_active_file(reminders):
"""Rewrite active file without done items"""
pending = [r for r in reminders if r['状态'] != 'done']
with open(ACTIVE_FILE, 'w', encoding='utf-8') as f:
f.write("# 提醒事项表\n\n")
f.write("## 待办事项Pending\n\n")
f.write("| 事项 | 截止日期 | 优先级 | 状态 | 备注 |\n")
f.write("|------|----------|--------|------|------|\n")
for r in pending:
f.write(f"| {r['事项']} | {r['截止日期']} | {r['优先级']} | {r['状态']} | {r['备注']} |\n")
f.write("\n## 使用说明\n\n")
f.write("1. **添加事项**:在表格中新增一行\n")
f.write("2. **截止日期**:格式 YYYY-MM-DD空着默认为明天\n")
f.write("3. **优先级**:高/中/低,空着默认为中\n")
f.write("4. **状态**pending待办/ done已完成\n")
f.write("5. **每天早上8:00自动检查**,到期事项会通知你\n\n")
f.write("## 已完成归档\n\n")
f.write("已完成的事项会自动移动到 archive/ 目录\n")
def main():
"""Main function - show all pending reminders as todo list"""
# Check if file exists
if not ACTIVE_FILE.exists():
print("No reminders file found")
return
# Read and parse
with open(ACTIVE_FILE, 'r', encoding='utf-8') as f:
content = f.read()
reminders = parse_table(content)
# Normalize and filter for pending only
reminders = [normalize_reminder(r) for r in reminders]
pending_reminders = [r for r in reminders if r['状态'] == 'pending']
if not pending_reminders:
# No pending reminders - silent
return
# Sort and format
pending_reminders = sort_reminders(pending_reminders)
notification = format_notification(pending_reminders)
if notification:
print(notification)
# Archive done items (optional - uncomment if you want auto-archive)
# archive_done_reminders(reminders)
# update_active_file(reminders)
if __name__ == "__main__":
main()