dfd8421dc6
**Storage Layer:** - Database 类(aiosqlite + WAL + 并发保护) - WikiPage 数据模型 - fix_dirty_states 恢复机制 - FTS5 全文搜索支持 - 完整的 SQLite 表结构 **Service Layer:** - CacheService(LRU 缓存 + TTL + 大小限制) - QueryService(查询服务) - ParserService(Markdown 解析) - IndexerService(索引服务) - GraphService(链接图服务) **Tool Layer (8 个 MCP Tools):** - wiki_query - FTS5 全文搜索 + 标签过滤 - memory_bridge - 按工具来源浏览 - wiki_status - 索引状态 - wiki_lint - 健康审计 - cross_linker - 缺失链接发现 - tag_taxonomy - 标签一致性 - wiki_synthesize - 跨概念综合分析 - daily_update - 日常维护 + hot.md 生成 **MCP Protocol Layer:** - MCP 协议解析和封装 - 工具注册和路由 - 错误处理和日志 - stdio 模式支持 **配置和部署:** - requirements.txt - config.example.yaml - ecosystem.config.cjs (PM2) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
113 lines
3.8 KiB
Python
113 lines
3.8 KiB
Python
"""
|
||
Tool Layer - memory_bridge 工具
|
||
|
||
按 AI 工具来源浏览和对比 wiki 知识。
|
||
|
||
参考设计文档:第 2.2 节
|
||
"""
|
||
|
||
import logging
|
||
from typing import Dict, Any, Optional
|
||
from datetime import datetime
|
||
from ..services import QueryService
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class MemoryBridgeTool:
|
||
"""memory_bridge 工具实现"""
|
||
|
||
def __init__(self, query_service: QueryService):
|
||
self.query_service = query_service
|
||
|
||
async def handle(self, tool_name: str = "claude", date_range: str = "") -> Dict[str, Any]:
|
||
"""
|
||
按 AI 工具来源浏览和对比 wiki 知识
|
||
|
||
Args:
|
||
tool_name: AI 工具名称(claude/web_reader/gitea/other)
|
||
date_range: 日期范围(如 "2024-01-01:2024-12-31" 或空字符串表示不限)
|
||
|
||
Returns:
|
||
{
|
||
"entries": [
|
||
{
|
||
"path": "practices/moziplus-orchestration.md",
|
||
"title": "moziplus 编排实践",
|
||
"summary": "...",
|
||
"updated_at": "2024-06-15T10:30:00",
|
||
"relevance_score": 0.85
|
||
}
|
||
],
|
||
"total": 12,
|
||
"tool_name": "claude",
|
||
"date_range": "2024-01-01:2024-12-31"
|
||
}
|
||
"""
|
||
# 按工具来源搜索
|
||
pages = await self.query_service.search_by_source_tool(tool_name, limit=100)
|
||
|
||
# 按日期范围过滤
|
||
if date_range:
|
||
try:
|
||
start_str, end_str = date_range.split(":")
|
||
start_date = datetime.fromisoformat(start_str)
|
||
end_date = datetime.fromisoformat(end_str)
|
||
|
||
filtered = []
|
||
for page in pages:
|
||
updated = datetime.fromisoformat(page.updated_at)
|
||
if start_date <= updated <= end_date:
|
||
filtered.append(page)
|
||
pages = filtered
|
||
except Exception as e:
|
||
logger.warning(f"Invalid date_range format '{date_range}': {e}")
|
||
|
||
# 格式化结果
|
||
entries = []
|
||
for page in pages:
|
||
# 计算相关性分数(基于摘要长度和更新时间)
|
||
recency_days = (datetime.now() - datetime.fromisoformat(page.updated_at)).days
|
||
relevance_score = max(0.1, 1.0 - recency_days / 365) # 简单衰减
|
||
|
||
entries.append({
|
||
"path": page.path,
|
||
"title": page.title,
|
||
"summary": page.summary,
|
||
"updated_at": page.updated_at,
|
||
"relevance_score": round(relevance_score, 2)
|
||
})
|
||
|
||
# 按相关性排序
|
||
entries.sort(key=lambda x: x["relevance_score"], reverse=True)
|
||
|
||
return {
|
||
"entries": entries[:50], # 最多返回 50 条
|
||
"total": len(entries),
|
||
"tool_name": tool_name,
|
||
"date_range": date_range
|
||
}
|
||
|
||
def get_schema(self) -> dict:
|
||
"""返回 MCP Tool schema"""
|
||
return {
|
||
"name": "memory_bridge",
|
||
"description": "按 AI 工具来源浏览和对比 wiki 知识",
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"tool_name": {
|
||
"type": "string",
|
||
"default": "claude",
|
||
"description": "AI 工具名称(claude/web_reader/gitea/other)",
|
||
"enum": ["claude", "web_reader", "gitea", "other"]
|
||
},
|
||
"date_range": {
|
||
"type": "string",
|
||
"default": "",
|
||
"description": "日期范围,格式:YYYY-MM-DD:YYYY-MM-DD"
|
||
}
|
||
}
|
||
}
|
||
}
|