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:
@@ -0,0 +1,260 @@
|
||||
"""
|
||||
Journal Organizer Agent HTTP 服务器
|
||||
|
||||
提供 REST API 接口,供 Obsidian 插件调用
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any
|
||||
from flask import Flask, request, jsonify
|
||||
from flask_cors import CORS
|
||||
from .conversation.conversational_agent import ConversationalAgent
|
||||
from .config import Config
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 创建 Flask 应用
|
||||
app = Flask(__name__)
|
||||
CORS(app) # 启用 CORS 支持
|
||||
|
||||
# 初始化 Agent
|
||||
config = Config()
|
||||
agent = ConversationalAgent(config)
|
||||
|
||||
# 存储对话历史
|
||||
conversations: Dict[str, List[Dict[str, Any]]] = {}
|
||||
|
||||
|
||||
@app.route("/health", methods=["GET"])
|
||||
def health_check():
|
||||
"""
|
||||
健康检查端点
|
||||
|
||||
Returns:
|
||||
JSON: { "status": "ok", "timestamp": "ISO 8601 时间戳" }
|
||||
"""
|
||||
return jsonify(
|
||||
{"status": "ok", "timestamp": datetime.now().isoformat(), "agent": "ready"}
|
||||
)
|
||||
|
||||
|
||||
@app.route("/api/chat", methods=["POST"])
|
||||
def chat():
|
||||
"""
|
||||
对话端点
|
||||
|
||||
Request JSON:
|
||||
{
|
||||
"message": "用户消息",
|
||||
"conversation_id": "对话 ID",
|
||||
"timestamp": "ISO 8601 时间戳"
|
||||
}
|
||||
|
||||
Response JSON:
|
||||
{
|
||||
"message": "Agent 响应",
|
||||
"suggestions": ["建议1", "建议2"],
|
||||
"status": "success|error|waiting_input",
|
||||
"conversation_id": "对话 ID",
|
||||
"timestamp": "ISO 8601 时间戳"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
if not data or "message" not in data:
|
||||
return jsonify({"message": "错误:缺少 'message' 字段", "status": "error"}), 400
|
||||
|
||||
user_message = data["message"]
|
||||
conversation_id = data.get("conversation_id", "default")
|
||||
|
||||
logger.info(f"[{conversation_id}] 用户消息: {user_message}")
|
||||
|
||||
# 初始化对话历史
|
||||
if conversation_id not in conversations:
|
||||
conversations[conversation_id] = []
|
||||
|
||||
# 添加用户消息到历史
|
||||
conversations[conversation_id].append(
|
||||
{
|
||||
"role": "user",
|
||||
"content": user_message,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}
|
||||
)
|
||||
|
||||
# 调用 Agent 处理消息
|
||||
response = agent.process_message(
|
||||
user_message, conversation_id, conversations[conversation_id]
|
||||
)
|
||||
|
||||
# 添加 Agent 响应到历史
|
||||
conversations[conversation_id].append(
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": response.get("message", ""),
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}
|
||||
)
|
||||
|
||||
logger.info(f"[{conversation_id}] Agent 响应: {response['message'][:100]}...")
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
"message": response.get("message", ""),
|
||||
"suggestions": response.get("suggestions", []),
|
||||
"status": response.get("status", "success"),
|
||||
"conversation_id": conversation_id,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Chat 端点错误: {e}", exc_info=True)
|
||||
return jsonify({"message": f"服务器错误: {str(e)}", "status": "error"}), 500
|
||||
|
||||
|
||||
@app.route("/api/history/<conversation_id>", methods=["GET"])
|
||||
def get_history(conversation_id: str):
|
||||
"""
|
||||
获取对话历史
|
||||
|
||||
Args:
|
||||
conversation_id: 对话 ID
|
||||
|
||||
Response JSON:
|
||||
{
|
||||
"messages": [
|
||||
{ "role": "user", "content": "...", "timestamp": "..." },
|
||||
{ "role": "assistant", "content": "...", "timestamp": "..." }
|
||||
],
|
||||
"conversation_id": "对话 ID"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
messages = conversations.get(conversation_id, [])
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
"messages": messages,
|
||||
"conversation_id": conversation_id,
|
||||
"count": len(messages),
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取历史错误: {e}")
|
||||
return jsonify({"message": f"错误: {str(e)}", "status": "error"}), 500
|
||||
|
||||
|
||||
@app.route("/api/history/<conversation_id>", methods=["DELETE"])
|
||||
def clear_history(conversation_id: str):
|
||||
"""
|
||||
清除对话历史
|
||||
|
||||
Args:
|
||||
conversation_id: 对话 ID
|
||||
|
||||
Response JSON:
|
||||
{ "status": "success", "conversation_id": "对话 ID" }
|
||||
"""
|
||||
try:
|
||||
if conversation_id in conversations:
|
||||
del conversations[conversation_id]
|
||||
|
||||
logger.info(f"已清除对话历史: {conversation_id}")
|
||||
|
||||
return jsonify({"status": "success", "conversation_id": conversation_id})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"清除历史错误: {e}")
|
||||
return jsonify({"message": f"错误: {str(e)}", "status": "error"}), 500
|
||||
|
||||
|
||||
@app.route("/api/suggestions/<conversation_id>", methods=["GET"])
|
||||
def get_suggestions(conversation_id: str):
|
||||
"""
|
||||
获取建议
|
||||
|
||||
Args:
|
||||
conversation_id: 对话 ID
|
||||
|
||||
Response JSON:
|
||||
{
|
||||
"suggestions": ["建议1", "建议2"],
|
||||
"conversation_id": "对话 ID"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
history = conversations.get(conversation_id, [])
|
||||
|
||||
# 调用 Agent 生成建议
|
||||
suggestions = agent.generate_suggestions(history)
|
||||
|
||||
return jsonify({"suggestions": suggestions, "conversation_id": conversation_id})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取建议错误: {e}")
|
||||
return jsonify({"suggestions": [], "status": "error"}), 500
|
||||
|
||||
|
||||
@app.route("/api/status", methods=["GET"])
|
||||
def get_status():
|
||||
"""
|
||||
获取 Agent 状态
|
||||
|
||||
Response JSON:
|
||||
{
|
||||
"status": "ready",
|
||||
"conversations": 对话数量,
|
||||
"uptime": "运行时间",
|
||||
"version": "版本号"
|
||||
}
|
||||
"""
|
||||
return jsonify(
|
||||
{
|
||||
"status": "ready",
|
||||
"conversations": len(conversations),
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"version": "1.0.0",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def not_found(error):
|
||||
"""处理 404 错误"""
|
||||
return jsonify({"message": "端点不存在", "status": "error"}), 404
|
||||
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internal_error(error):
|
||||
"""处理 500 错误"""
|
||||
logger.error(f"内部服务器错误: {error}")
|
||||
return jsonify({"message": "内部服务器错误", "status": "error"}), 500
|
||||
|
||||
|
||||
def run_server(host: str = "0.0.0.0", port: int = 5000, debug: bool = False):
|
||||
"""
|
||||
启动 HTTP 服务器
|
||||
|
||||
Args:
|
||||
host: 绑定的主机地址
|
||||
port: 绑定的端口
|
||||
debug: 是否启用调试模式
|
||||
"""
|
||||
logger.info(f"启动 Journal Organizer Agent 服务器...")
|
||||
logger.info(f"监听地址: {host}:{port}")
|
||||
logger.info(f"调试模式: {debug}")
|
||||
|
||||
app.run(host=host, port=port, debug=debug, threaded=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_server(debug=True)
|
||||
Reference in New Issue
Block a user