统一 Repository 方案:添加 db 基类和子图模型 + 通讯录 API 支持真实数据库
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Has been cancelled
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Has been cancelled
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
"""
|
||||
通讯录子图API调用工具
|
||||
Contact Subgraph API Client
|
||||
通讯录子图 API 调用工具
|
||||
支持模拟数据和真实数据库两种模式
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, Optional, List
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass
|
||||
@@ -10,6 +9,8 @@ from dataclasses import dataclass
|
||||
from .state import Contact, Email
|
||||
|
||||
|
||||
# ========== 模拟数据(保留作为备选)==========
|
||||
|
||||
# 模拟数据库
|
||||
MOCK_CONTACTS_DB = {}
|
||||
MOCK_EMAILS_DB = []
|
||||
@@ -18,13 +19,75 @@ MOCK_EMAILS_DB = []
|
||||
@dataclass
|
||||
class ContactAPIClient:
|
||||
"""
|
||||
通讯录API客户端 - 可扩展支持多种后端
|
||||
通讯录 API 客户端 - 支持真实数据库和模拟模式
|
||||
|
||||
使用方式:
|
||||
1. 真实数据库模式:传入 conn 参数
|
||||
2. 模拟模式:不传入 conn,或 conn 为 None
|
||||
"""
|
||||
|
||||
def __init__(self, conn=None):
|
||||
"""
|
||||
初始化
|
||||
|
||||
Args:
|
||||
conn: 数据库连接(来自 checkpointer.conn),为 None 时使用模拟模式
|
||||
"""
|
||||
self.conn = conn
|
||||
self._use_db = conn is not None
|
||||
|
||||
if self._use_db:
|
||||
try:
|
||||
from ...db.models import ContactRepository, ContactEntity
|
||||
self._repo = ContactRepository(conn)
|
||||
except Exception as e:
|
||||
print(f"Repository 初始化失败,回退到模拟模式: {e}")
|
||||
self._use_db = False
|
||||
self._repo = None
|
||||
|
||||
# ========== 真实数据库方法 ==========
|
||||
|
||||
async def list_contacts_db(self, user_id: str = "default") -> List[Contact]:
|
||||
"""真实数据库:获取联系人列表"""
|
||||
if not self._repo:
|
||||
return await self.list_contacts_mock(user_id)
|
||||
|
||||
entities = await self._repo.list_by_user(user_id)
|
||||
return [
|
||||
Contact(
|
||||
id=e.id,
|
||||
name=e.name,
|
||||
phone=e.phone,
|
||||
email=e.email,
|
||||
company=e.company,
|
||||
position=e.position,
|
||||
created_at=e.created_at
|
||||
)
|
||||
for e in entities
|
||||
]
|
||||
|
||||
async def add_contact_db(self, user_id: str, contact: Contact) -> bool:
|
||||
"""真实数据库:添加联系人"""
|
||||
if not self._repo:
|
||||
return await self.save_contact_mock(user_id, contact)
|
||||
|
||||
from ...db.models import ContactEntity
|
||||
entity = ContactEntity(
|
||||
user_id=user_id,
|
||||
name=contact.name,
|
||||
phone=contact.phone,
|
||||
email=contact.email,
|
||||
company=contact.company,
|
||||
position=contact.position,
|
||||
created_at=contact.created_at or datetime.now().isoformat()
|
||||
)
|
||||
await self._repo.insert(entity)
|
||||
return True
|
||||
|
||||
# ========== 模拟数据方法(保留)==========
|
||||
|
||||
def list_contacts_mock(self, user_id: str = "default") -> List[Contact]:
|
||||
"""
|
||||
模拟查询联系人列表
|
||||
"""
|
||||
"""模拟查询联系人列表"""
|
||||
if user_id not in MOCK_CONTACTS_DB:
|
||||
# 初始化一些示例数据
|
||||
MOCK_CONTACTS_DB[user_id] = [
|
||||
@@ -54,16 +117,13 @@ class ContactAPIClient:
|
||||
company="咨询公司",
|
||||
position="顾问",
|
||||
created_at=datetime.now().isoformat()
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
return MOCK_CONTACTS_DB[user_id]
|
||||
|
||||
def extract_contact_info_mock(self, query: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
模拟从查询中提取联系人信息
|
||||
"""
|
||||
# 简化的提取逻辑
|
||||
"""模拟从查询中提取联系人信息"""
|
||||
import re
|
||||
|
||||
# 提取邮箱
|
||||
@@ -71,11 +131,8 @@ class ContactAPIClient:
|
||||
# 提取手机号
|
||||
phone_match = re.search(r'1[3-9]\d{9}', query)
|
||||
# 提取姓名(简单匹配)
|
||||
# 先看是否有"添加"等关键词
|
||||
if any(keyword in query for keyword in ["添加", "add"]):
|
||||
# 尝试提取姓名
|
||||
name = "未知"
|
||||
# 简单的逻辑:去掉关键词、去掉邮箱和电话后剩下的
|
||||
clean_query = query
|
||||
if email_match:
|
||||
clean_query = clean_query.replace(email_match.group(), "")
|
||||
@@ -95,9 +152,7 @@ class ContactAPIClient:
|
||||
return None
|
||||
|
||||
def save_contact_mock(self, user_id: str, contact: Contact) -> bool:
|
||||
"""
|
||||
模拟保存联系人
|
||||
"""
|
||||
"""模拟保存联系人"""
|
||||
if user_id not in MOCK_CONTACTS_DB:
|
||||
MOCK_CONTACTS_DB[user_id] = []
|
||||
|
||||
@@ -108,21 +163,18 @@ class ContactAPIClient:
|
||||
return True
|
||||
|
||||
def list_emails_mock(self) -> List[Email]:
|
||||
"""
|
||||
模拟查询邮件列表
|
||||
"""
|
||||
"""模拟查询邮件列表"""
|
||||
global MOCK_EMAILS_DB
|
||||
|
||||
if not MOCK_EMAILS_DB:
|
||||
# 初始化一些示例邮件
|
||||
MOCK_EMAILS_DB = [
|
||||
Email(
|
||||
id="1",
|
||||
subject="会议邀请:AI技术分享",
|
||||
subject="会议邀请:AI 技术分享",
|
||||
sender="admin@example.com",
|
||||
recipients=["user@example.com"],
|
||||
date=datetime.now().isoformat(),
|
||||
body="你好,下周一将举办AI技术分享会,欢迎参加。"
|
||||
body="你好,下周一将举办 AI 技术分享会,欢迎参加。"
|
||||
),
|
||||
Email(
|
||||
id="2",
|
||||
@@ -131,16 +183,13 @@ class ContactAPIClient:
|
||||
recipients=["user@example.com"],
|
||||
date=datetime.now().isoformat(),
|
||||
body="项目进度良好,继续保持。"
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
return MOCK_EMAILS_DB
|
||||
|
||||
def generate_email_draft_mock(self, query: str) -> Dict[str, str]:
|
||||
"""
|
||||
模拟生成邮件草稿
|
||||
"""
|
||||
# 简单的模板生成
|
||||
"""模拟生成邮件草稿"""
|
||||
return {
|
||||
"subject": f"Re: {query}",
|
||||
"recipient": "recipient@example.com",
|
||||
@@ -148,10 +197,9 @@ class ContactAPIClient:
|
||||
}
|
||||
|
||||
def send_email_mock(self, recipient: str, subject: str, body: str) -> Dict[str, Any]:
|
||||
"""
|
||||
模拟发送邮件
|
||||
"""
|
||||
# 记录到模拟数据库
|
||||
"""模拟发送邮件"""
|
||||
global MOCK_EMAILS_DB
|
||||
|
||||
MOCK_EMAILS_DB.append(
|
||||
Email(
|
||||
id=str(len(MOCK_EMAILS_DB) + 1),
|
||||
@@ -169,10 +217,7 @@ class ContactAPIClient:
|
||||
}
|
||||
|
||||
def sniff_contacts_mock(self, query: str) -> Dict[str, Any]:
|
||||
"""
|
||||
模拟智能嗅探联系人
|
||||
"""
|
||||
# 简化的检测逻辑
|
||||
"""模拟智能嗅探联系人"""
|
||||
import re
|
||||
|
||||
emails = re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', query)
|
||||
@@ -191,31 +236,36 @@ class ContactAPIClient:
|
||||
"count": len(contacts),
|
||||
"suggestion": "是否添加这些联系人?"
|
||||
}
|
||||
|
||||
# 公共方法
|
||||
def list_contacts(self, user_id: str = "default") -> List[Contact]:
|
||||
"""查询联系人列表"""
|
||||
|
||||
# ========== 公共方法(自动选择模式)==========
|
||||
|
||||
async def list_contacts(self, user_id: str = "default") -> List[Contact]:
|
||||
"""获取联系人列表(自动选择数据库或模拟模式)"""
|
||||
if self._use_db:
|
||||
return await self.list_contacts_db(user_id)
|
||||
return self.list_contacts_mock(user_id)
|
||||
|
||||
def add_contact(self, user_id: str, contact: Contact) -> bool:
|
||||
"""添加联系人"""
|
||||
|
||||
async def add_contact(self, user_id: str, contact: Contact) -> bool:
|
||||
"""添加联系人(自动选择数据库或模拟模式)"""
|
||||
if self._use_db:
|
||||
return await self.add_contact_db(user_id, contact)
|
||||
return self.save_contact_mock(user_id, contact)
|
||||
|
||||
def list_emails(self, user_id: str = "default") -> List[Email]:
|
||||
"""查询邮件列表"""
|
||||
|
||||
async def list_emails(self, user_id: str = "default") -> List[Email]:
|
||||
"""查询邮件列表(目前用模拟)"""
|
||||
return self.list_emails_mock()
|
||||
|
||||
def generate_email_draft(self, query: str) -> Dict[str, str]:
|
||||
"""生成邮件草稿"""
|
||||
|
||||
async def generate_email_draft(self, query: str) -> Dict[str, str]:
|
||||
"""生成邮件草稿(目前用模拟)"""
|
||||
return self.generate_email_draft_mock(query)
|
||||
|
||||
def send_email(self, user_id: str, recipient: str, subject: str, body: str) -> bool:
|
||||
"""发送邮件"""
|
||||
|
||||
async def send_email(self, user_id: str, recipient: str, subject: str, body: str) -> bool:
|
||||
"""发送邮件(目前用模拟)"""
|
||||
result = self.send_email_mock(recipient, subject, body)
|
||||
return result.get("success", False)
|
||||
|
||||
def sniff_contacts(self, query: str) -> List[Contact]:
|
||||
"""智能嗅探联系人"""
|
||||
|
||||
async def sniff_contacts(self, query: str) -> List[Contact]:
|
||||
"""智能嗅探联系人(目前用模拟)"""
|
||||
result = self.sniff_contacts_mock(query)
|
||||
contact_dicts = result.get("contacts", [])
|
||||
return [
|
||||
@@ -232,5 +282,5 @@ class ContactAPIClient:
|
||||
]
|
||||
|
||||
|
||||
# 单例实例
|
||||
# 全局实例(模拟模式,保留向后兼容)
|
||||
contact_api = ContactAPIClient()
|
||||
|
||||
Reference in New Issue
Block a user