Initial project setup: Obsidian intelligent journal organizer

- Add core agent architecture with Command + Skill pattern
- Implement Claude API integration for content analysis
- Add Obsidian REST API integration for vault operations
- Create conversational interface (v2.0) with natural language processing
- Add comprehensive configuration management and validation
- Include project documentation and developer guides
- Set up testing framework with unit, integration, and property tests
- Add Kiro specs for Claude API configuration and code quality improvements
- Configure project steering files for development guidelines
This commit is contained in:
windyboy
2025-12-31 17:55:10 +08:00
parent 3200ad3dd5
commit f7e54692a9
67 changed files with 23088 additions and 0 deletions
+254
View File
@@ -0,0 +1,254 @@
"""
对话式 Agent 的命令行入口
支持交互式对话
"""
import argparse
import asyncio
import logging
import sys
from typing import Dict, Any, Optional, List
from typing import Dict, Any, Optional, List
# Handle imports with both relative and absolute paths
try:
from .main import JournalOrganizerAgent
from .conversation import ConversationalAgent
except ImportError:
# Fallback to absolute imports when running as script
from main import JournalOrganizerAgent
from conversation import ConversationalAgent
class ChatInterface:
"""对话式 Agent 的命令行界面"""
def __init__(self, config_file: Optional[str] = None) -> None:
"""
初始化聊天界面
Args:
config_file: 配置文件路径
"""
self.logger: logging.Logger = logging.getLogger("ChatInterface")
# 初始化 Agent
self.journal_agent: JournalOrganizerAgent = JournalOrganizerAgent(config_file)
self.conversational_agent: ConversationalAgent = ConversationalAgent(
self.journal_agent.agent, self.journal_agent.config
)
async def run_interactive(self) -> None:
"""
运行交互式对话
"""
print(f"\n{'='*60}")
print("Obsidian 智能日记整理 Agent - 对话模式")
print(f"{'='*60}\n")
# 显示欢迎消息
welcome_msg = await self.conversational_agent.initialize()
print(f"\n🤖 助手: {welcome_msg}\n")
# 交互循环
while True:
try:
# 获取用户输入
user_input: str = input("👤 您: ").strip()
if not user_input:
continue
# 处理特殊命令
if user_input.lower() in ["exit", "quit", "退出"]:
print("\n👋 再见!\n")
break
if user_input.lower() in ["help", "帮助"]:
self._show_help()
continue
if user_input.lower() in ["history", "历史"]:
self._show_history()
continue
if user_input.lower() in ["status", "状态"]:
self._show_status()
continue
if user_input.lower() in ["clear", "清除"]:
self.conversational_agent.clear_history()
print("\n✓ 对话历史已清除\n")
continue
# 处理用户消息
print("\n⏳ 处理中...\n")
response = await self.conversational_agent.chat(user_input)
# 显示响应
print(f"🤖 助手: {response.message}")
# 显示建议
if response.suggestions:
print("\n💡 您可以尝试:")
for i, suggestion in enumerate(response.suggestions, 1):
print(f" {i}. {suggestion}")
print()
except KeyboardInterrupt:
print("\n\n👋 再见!\n")
break
except Exception as e:
self.logger.error(f"错误: {str(e)}", exc_info=True)
print(f"\n❌ 发生错误: {str(e)}\n")
async def run_single_query(self, query: str) -> None:
"""
运行单个查询
Args:
query: 用户查询
"""
# 初始化
await self.conversational_agent.initialize()
# 处理查询
response = await self.conversational_agent.chat(query)
# 输出结果
output_data: Dict[str, Any] = {
"message": response.message,
"status": response.status,
"suggestions": response.suggestions,
"metadata": response.metadata,
}
print(json.dumps(output_data, ensure_ascii=False, indent=2))
def _show_help(self) -> None:
"""
显示帮助信息
"""
help_text = """
🆘 可用命令:
对话命令:
- 直接输入您的需求,例如: "整理今天的日记"
- "分析本周的主题"
- "导出月度总结"
系统命令:
- help / 帮助 显示此帮助信息
- history / 历史 显示对话历史
- status / 状态 显示当前状态
- clear / 清除 清除对话历史
- exit / quit / 退出 退出程序
示例对话:
👤 您: 帮我整理一下昨天的日记
🤖 助手: 好的,我来帮您整理昨天的日记...
👤 您: 分析一下这周的主题
🤖 助手: 这周的主题主要集中在...
"""
print(help_text)
def _show_history(self) -> None:
"""
显示对话历史
"""
history: List[
Dict[str, str]
] = self.conversational_agent.get_conversation_history()
if not history:
print("\n📭 对话历史为空\n")
return
print("\n📜 对话历史:\n")
for msg in history:
role: str = "👤 您" if msg["role"] == "user" else "🤖 助手"
content: str = msg["content"]
if len(content) > 100:
content = f"{content[:100]}..."
print(f"{role}: {content}")
print()
def _show_status(self) -> None:
"""
显示当前状态
"""
summary: Dict[str, Any] = self.conversational_agent.get_state_summary()
print("\n📊 当前状态:\n")
print(f"总消息数: {summary['total_messages']}")
print(f"总任务数: {summary['stats']['total_tasks']}")
print(f"成功任务: {summary['stats']['successful_tasks']}")
print(f"失败任务: {summary['stats']['failed_tasks']}")
if summary["current_task"]:
print(f"\n当前任务: {summary['current_task']['command']}")
print(f"状态: {summary['current_task']['status']}")
print()
async def main() -> Optional[int]:
"""
主函数
"""
parser: argparse.ArgumentParser = argparse.ArgumentParser(
description="Obsidian 智能日记整理 Agent - 对话模式",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
# 启动交互式对话
python -m journal_organizer.chat_main
# 处理单个查询
python -m journal_organizer.chat_main --query "整理今天的日记"
# 使用指定配置文件
python -m journal_organizer.chat_main --config /path/to/config.yaml
""",
)
parser.add_argument("--config", type=str, help="配置文件路径")
parser.add_argument("--query", type=str, help="单个查询(不进入交互模式)")
parser.add_argument(
"--log-level",
type=str,
default="INFO",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help="日志级别",
)
args: argparse.Namespace = parser.parse_args()
# 设置日志
logging.basicConfig(
level=getattr(logging, args.log_level),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
# 初始化聊天界面
chat: ChatInterface = ChatInterface(args.config)
# 运行
if args.query:
# 单个查询模式
await chat.run_single_query(args.query)
else:
# 交互模式
await chat.run_interactive()
return None
if __name__ == "__main__":
exit_code: Optional[int] = asyncio.run(main())
sys.exit(exit_code or 0)