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

View File

@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""
Email Queue Processor - Handle user commands for pending emails
Reads pending_emails.json and executes user commands (archive/keep/reply)
"""
import json
import imaplib
import os
import sys
from datetime import datetime
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent
DATA_FILE = SCRIPT_DIR / "data" / "pending_emails.json"
def load_pending():
"""Load pending emails from JSON file"""
if not DATA_FILE.exists():
return {}
with open(DATA_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
def save_pending(pending):
"""Save pending emails to JSON file"""
DATA_FILE.parent.mkdir(exist_ok=True)
with open(DATA_FILE, 'w', encoding='utf-8') as f:
json.dump(pending, f, indent=2, ensure_ascii=False)
def connect_imap(config):
"""Connect to IMAP server"""
mail = imaplib.IMAP4_SSL(config['imap']['host'], config['imap']['port'])
mail.login(config['imap']['email'], config['imap']['password'])
return mail
def show_pending_list():
"""Display all pending emails"""
pending = load_pending()
if not pending:
print("📭 没有待处理的邮件")
return
print(f"\n📧 待处理邮件列表 ({len(pending)} 封)")
print("=" * 60)
# Sort by email_date
sorted_items = sorted(
pending.items(),
key=lambda x: x[1].get('email_date', '')
)
for msg_id, data in sorted_items:
if data.get('status') == 'pending':
print(f"\n🆔 {msg_id}")
print(f" 主题: {data.get('subject', 'N/A')[:50]}")
print(f" 发件人: {data.get('sender', 'N/A')}")
print(f" 收件人: {data.get('recipient', 'N/A')}")
print(f" 时间: {data.get('email_date', 'N/A')}")
print(f" 摘要: {data.get('summary', 'N/A')[:80]}")
print("\n" + "=" * 60)
print("\n可用指令:")
print(" • 归档 [ID] - 移动到 Archive 文件夹")
print(" • 保留 [ID] - 标记已读,留在收件箱")
print(" • 删除 [ID] - 移动到 Trash")
print(" • 全部处理 - 列出所有并批量操作")
def archive_email(config, msg_id):
"""Archive a specific email by ID"""
pending = load_pending()
if msg_id not in pending:
print(f"❌ 未找到邮件 ID: {msg_id}")
return False
email_data = pending[msg_id]
uid = email_data.get('imap_uid')
if not uid:
print(f"❌ 邮件 {msg_id} 没有 UID")
return False
try:
mail = connect_imap(config)
mail.select('INBOX')
# Copy to Archive
result = mail.copy(uid, 'Archive')
if result[0] == 'OK':
# Mark original as deleted
mail.store(uid, '+FLAGS', '\\Deleted')
mail.expunge()
# Update status
pending[msg_id]['status'] = 'done'
pending[msg_id]['action'] = 'archived'
pending[msg_id]['processed_at'] = datetime.now().isoformat()
save_pending(pending)
print(f"✅ 已归档: {email_data.get('subject', 'N/A')[:40]}")
return True
else:
print(f"❌ 归档失败: {result}")
return False
except Exception as e:
print(f"❌ 错误: {e}")
return False
finally:
try:
mail.logout()
except:
pass
def keep_email(config, msg_id):
"""Keep email in inbox, mark as read"""
pending = load_pending()
if msg_id not in pending:
print(f"❌ 未找到邮件 ID: {msg_id}")
return False
email_data = pending[msg_id]
uid = email_data.get('imap_uid')
if not uid:
print(f"❌ 邮件 {msg_id} 没有 UID")
return False
try:
mail = connect_imap(config)
mail.select('INBOX')
# Mark as read (Seen)
mail.store(uid, '+FLAGS', '\\Seen')
# Update status
pending[msg_id]['status'] = 'done'
pending[msg_id]['action'] = 'kept'
pending[msg_id]['processed_at'] = datetime.now().isoformat()
save_pending(pending)
print(f"✅ 已保留: {email_data.get('subject', 'N/A')[:40]}")
return True
except Exception as e:
print(f"❌ 错误: {e}")
return False
finally:
try:
mail.logout()
except:
pass
def delete_email(config, msg_id):
"""Move email to Trash"""
pending = load_pending()
if msg_id not in pending:
print(f"❌ 未找到邮件 ID: {msg_id}")
return False
email_data = pending[msg_id]
uid = email_data.get('imap_uid')
if not uid:
print(f"❌ 邮件 {msg_id} 没有 UID")
return False
try:
mail = connect_imap(config)
mail.select('INBOX')
# Copy to Trash
result = mail.copy(uid, 'Trash')
if result[0] == 'OK':
mail.store(uid, '+FLAGS', '\\Deleted')
mail.expunge()
# Update status
pending[msg_id]['status'] = 'done'
pending[msg_id]['action'] = 'deleted'
pending[msg_id]['processed_at'] = datetime.now().isoformat()
save_pending(pending)
print(f"✅ 已删除: {email_data.get('subject', 'N/A')[:40]}")
return True
else:
print(f"❌ 删除失败: {result}")
return False
except Exception as e:
print(f"❌ 错误: {e}")
return False
finally:
try:
mail.logout()
except:
pass
def main():
"""Main function - show pending list"""
import json
# Load config
config_file = Path(__file__).parent / "config.json"
with open(config_file) as f:
config = json.load(f)
show_pending_list()
if __name__ == "__main__":
main()