""" 通讯录子图节点 - 完善版(使用API客户端) Contact Subgraph Nodes - Complete (with API Client) """ from typing import Dict, Any from datetime import datetime from .state import ContactState, ContactAction, Contact, Email from .api_client import contact_api # 模拟联系人数据库(临时存储) CONTACT_DB = {} def parse_intent(state: ContactState) -> ContactState: """ 解析用户意图节点 确定用户想做什么操作 """ state.current_phase = "intent_parsing" query_lower = state.user_query.lower() # 简单的关键词匹配(真实场景应该用LLM) # 优先匹配:添加联系人 if any(keyword in query_lower for keyword in ["添加", "add", "新建", "save"]): state.action = ContactAction.CONTACT_ADD elif any(keyword in query_lower for keyword in ["联系人", "contact", "list"]): state.action = ContactAction.CONTACT_LIST state.action_params = {"query": state.user_query} elif any(keyword in query_lower for keyword in ["邮件", "email", "inbox"]): state.action = ContactAction.EMAIL_LIST elif any(keyword in query_lower for keyword in ["发送邮件", "send email", "发邮件"]): state.action = ContactAction.EMAIL_SEND else: state.action = ContactAction.SNIFF_CONTACTS return state def list_contacts(state: ContactState) -> ContactState: """ 列出联系人节点 """ state.current_phase = "listing_contacts" # 使用API客户端获取联系人 state.contacts = contact_api.list_contacts_mock(state.user_id) state.success = True return state def add_contact(state: ContactState) -> ContactState: """ 添加联系人节点 """ state.current_phase = "adding_contact" # 从查询中提取联系人信息(简化版) query = state.user_query contact_data = contact_api.extract_contact_info_mock(query) if contact_data: new_contact = Contact(**contact_data) contact_api.save_contact_mock(state.user_id, new_contact) state.current_contact = new_contact state.success = True state.final_result = f"✅ 联系人 {new_contact.name} 添加成功" else: state.success = False state.error_message = "无法从查询中提取联系人信息" return state def list_emails(state: ContactState) -> ContactState: """ 列出邮件节点 """ state.current_phase = "listing_emails" # 使用API客户端获取邮件 state.emails = contact_api.list_emails_mock() state.success = True return state def generate_email_draft(state: ContactState) -> ContactState: """ 生成邮件草稿节点 """ state.current_phase = "generating_draft" # 使用API客户端生成邮件草稿 draft = contact_api.generate_email_draft_mock(state.user_query) state.draft_subject = draft.get("subject", "") state.draft_recipient = draft.get("recipient", "") state.draft_body = draft.get("body", "") # 进入人工审核状态 state.pending_review = True state.review_type = "email_send" state.review_prompt = "请确认是否发送此邮件" return state def human_review(state: ContactState) -> ContactState: """ 人工审核节点 这里会让用户确认/修改 """ state.current_phase = "reviewing" # 注意:真实的LangGraph会在这里使用interrupt()暂停 # 这里我们只设置状态,让外层处理 if state.review_approved is True: state.pending_review = False elif state.review_approved is False: state.pending_review = False state.error_message = "发送已取消" state.success = False return state def send_email(state: ContactState) -> ContactState: """ 发送邮件节点 """ state.current_phase = "sending_email" # 使用API客户端发送邮件 result = contact_api.send_email_mock( state.draft_recipient, state.draft_subject, state.draft_body ) if result.get("success"): state.success = True state.final_result = "✅ 邮件发送成功" else: state.success = False state.error_message = "邮件发送失败" return state def sniff_contacts(state: ContactState) -> ContactState: """ 智能嗅探节点 从对话中提取可能的联系人信息 """ state.current_phase = "sniffing" # 使用API客户端智能嗅探 sniffed = contact_api.sniff_contacts_mock(state.user_query) state.sniff_result = sniffed if sniffed.get("contacts"): state.sniffed_contacts = [ Contact(**contact) for contact in sniffed.get("contacts") ] state.sniff_confirmation_pending = True state.success = True return state def format_result(state: ContactState) -> ContactState: """ 格式化结果节点 - 精美展示 """ state.current_phase = "formatting" # 根据不同action生成不同的格式化输出 if state.action == ContactAction.CONTACT_LIST: result = [] result.append("═══════════════════════════════════════════") result.append("📇 联系人列表") result.append("═══════════════════════════════════════════") result.append("") if state.contacts: for i, contact in enumerate(state.contacts, 1): result.append(f"{i}. {contact.name}") if contact.phone: result.append(f" 📞 电话:{contact.phone}") if contact.email: result.append(f" 📧 邮箱:{contact.email}") if contact.company: result.append(f" 🏢 公司:{contact.company}") result.append("") else: result.append(" 暂无联系人") result.append("") result.append("═══════════════════════════════════════════") result.append("💡 提示:添加联系人 张三 13800138000 zhangsan@example.com") state.final_result = "\n".join(result) elif state.action == ContactAction.CONTACT_ADD: if state.final_result: state.final_result = state.final_result else: result = [] result.append("═══════════════════════════════════════════") result.append("📇 添加联系人") result.append("═══════════════════════════════════════════") result.append("") result.append(" ✅ 联系人添加成功") result.append("") result.append("═══════════════════════════════════════════") state.final_result = "\n".join(result) elif state.action == ContactAction.EMAIL_LIST: result = [] result.append("═══════════════════════════════════════════") result.append("📧 邮件列表") result.append("═══════════════════════════════════════════") result.append("") if state.emails: for i, email in enumerate(state.emails[:10], 1): result.append(f"{i}. {email.subject}") result.append(f" 👤 发件人:{email.sender}") if email.date: result.append(f" 📅 日期:{email.date}") result.append("") else: result.append(" 暂无邮件") result.append("") result.append("═══════════════════════════════════════════") state.final_result = "\n".join(result) elif state.action == ContactAction.EMAIL_SEND and state.pending_review: result = [] result.append("═══════════════════════════════════════════") result.append("📧 邮件草稿(待审核)") result.append("═══════════════════════════════════════════") result.append("") result.append(f"📌 主题:{state.draft_subject}") result.append(f"👤 收件人:{state.draft_recipient}") result.append("") result.append("📝 内容:") result.append(state.draft_body) result.append("") result.append("═══════════════════════════════════════════") result.append("💡 提示:确认发送/取消/修改内容") state.final_result = "\n".join(result) elif state.sniff_result and state.sniffed_contacts: result = [] result.append("═══════════════════════════════════════════") result.append("🕵️ 智能嗅探结果") result.append("═══════════════════════════════════════════") result.append("") result.append(f" 发现 {len(state.sniffed_contacts)} 个可能的联系人:") result.append("") for i, contact in enumerate(state.sniffed_contacts, 1): result.append(f"{i}. {contact.name}") if contact.phone: result.append(f" 📞 电话:{contact.phone}") if contact.email: result.append(f" 📧 邮箱:{contact.email}") result.append("") result.append("═══════════════════════════════════════════") state.final_result = "\n".join(result) else: if not state.final_result: state.final_result = "通讯录操作完成" state.current_phase = "done" return state def should_continue(state: ContactState) -> str: """ 条件路由:决定下一步该做什么 """ if state.error_message: return "format_result" # 如果在审核中,等待 if state.pending_review: return "format_result" # 根据action路由 if state.action == ContactAction.NONE: return "parse_intent" elif state.action == ContactAction.CONTACT_LIST: return "list_contacts" elif state.action == ContactAction.CONTACT_ADD: return "add_contact" elif state.action == ContactAction.EMAIL_LIST: return "list_emails" elif state.action == ContactAction.EMAIL_SEND: if state.pending_review: return "format_result" elif state.draft_subject and not state.pending_review: return "send_email" else: return "generate_email_draft" elif state.action == ContactAction.SNIFF_CONTACTS: return "sniff_contacts" else: return "format_result"