Files
windyboy f7e54692a9 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
2025-12-31 17:55:10 +08:00

255 lines
7.3 KiB
Python

"""
对话式 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)