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:
+254
@@ -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)
|
||||
Reference in New Issue
Block a user