大改,未验证

This commit is contained in:
2026-03-20 16:50:26 +08:00
parent c7ee292c4f
commit e14e3ee7a5
36 changed files with 1419 additions and 4805 deletions

View File

@@ -185,20 +185,20 @@ def get_agent_tools_stats():
try:
from src.web.service_manager import service_manager
agent_assistant = service_manager.get_agent_assistant()
tools = agent_assistant.agent_core.tool_manager.get_available_tools()
performance = agent_assistant.agent_core.tool_manager.get_tool_performance_report()
react_status = agent_assistant.react_agent.get_status()
tools = agent_assistant.react_agent.get_tool_definitions()
history = agent_assistant.react_agent.get_execution_history(20)
return jsonify({
"success": True,
"tools": tools,
"performance": performance
"status": react_status,
"recent_history": history
})
except Exception as e:
# 返回默认工具列表避免500错误
return jsonify({
"success": False,
"tools": [],
"performance": {},
"error": "工具统计暂时不可用"
"error": str(e)
})
@@ -213,15 +213,23 @@ def execute_agent_tool():
if not tool_name:
return jsonify({"error": "缺少工具名称tool"}), 400
result = service_manager.get_agent_assistant().agent_core.tool_manager.execute_tool_sync(tool_name, parameters)
return jsonify(result)
agent = service_manager.get_agent_assistant()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
result = loop.run_until_complete(
agent.react_agent._execute_tool(tool_name, parameters)
)
finally:
loop.close()
return jsonify({"success": True, "result": result})
except Exception as e:
return jsonify({"error": str(e)}), 500
@agent_bp.route('/tools/register', methods=['POST'])
def register_custom_tool():
"""注册自定义工具(仅登记元数据,函数为占位符"""
"""注册自定义工具(仅登记元数据)"""
try:
from src.web.service_manager import service_manager
data = request.get_json() or {}
@@ -230,14 +238,9 @@ def register_custom_tool():
if not name:
return jsonify({"error": "缺少工具名称"}), 400
def _placeholder_tool(**kwargs):
return {"message": f"自定义工具 {name} 已登记(占位),当前不可执行", "params": kwargs}
service_manager.get_agent_assistant().agent_core.tool_manager.register_tool(
name,
_placeholder_tool,
metadata={"description": description, "custom": True}
)
agent = service_manager.get_agent_assistant()
agent.register_tool(name, lambda **kw: {"message": f"自定义工具 {name} 占位", "params": kw},
metadata={"description": description, "custom": True})
return jsonify({"success": True, "message": "工具已注册"})
except Exception as e:
return jsonify({"error": str(e)}), 500
@@ -248,7 +251,7 @@ def unregister_custom_tool(name):
"""注销自定义工具"""
try:
from src.web.service_manager import service_manager
success = service_manager.get_agent_assistant().agent_core.tool_manager.unregister_tool(name)
success = service_manager.get_agent_assistant().unregister_tool(name)
return jsonify({"success": success})
except Exception as e:
return jsonify({"error": str(e)}), 500

View File

@@ -349,3 +349,68 @@ def get_conversation_analytics():
except Exception as e:
logger.error(f"获取对话分析数据失败: {e}")
return jsonify({"error": str(e)}), 500
# ==================== 会话管理 API ====================
@conversations_bp.route('/sessions')
def get_sessions():
"""获取会话列表(分页)"""
try:
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
status = request.args.get('status', '') # active, ended, 空=全部
search = request.args.get('search', '')
date_filter = request.args.get('date_filter', '')
result = history_manager.get_sessions_paginated(
page=page,
per_page=per_page,
status=status or None,
search=search,
date_filter=date_filter
)
return jsonify(result)
except Exception as e:
logger.error(f"获取会话列表失败: {e}")
return jsonify({"error": str(e)}), 500
@conversations_bp.route('/sessions/<session_id>')
def get_session_detail(session_id):
"""获取某个会话的完整消息列表"""
try:
limit = request.args.get('limit', 100, type=int)
offset = request.args.get('offset', 0, type=int)
result = history_manager.get_session_messages(
session_id=session_id,
limit=limit,
offset=offset
)
if 'error' in result:
return jsonify(result), 404
return jsonify({'success': True, **result})
except Exception as e:
logger.error(f"获取会话详情失败: {e}")
return jsonify({"error": str(e)}), 500
@conversations_bp.route('/sessions/<session_id>', methods=['DELETE'])
def delete_session(session_id):
"""删除会话及其所有消息"""
try:
success = history_manager.delete_session(session_id)
if success:
return jsonify({"success": True, "message": "会话已删除"})
else:
return jsonify({"error": "删除失败"}), 500
except Exception as e:
logger.error(f"删除会话失败: {e}")
return jsonify({"error": str(e)}), 500

View File

@@ -437,7 +437,6 @@ def get_error_log():
).limit(50).all()
errors = []
error_id = 1
for conv in conversations:
error_type = None
@@ -460,14 +459,17 @@ def get_error_log():
# 只记录有错误的对话
if error_type:
errors.append({
'id': error_id,
'id': conv.id,
'timestamp': conv.timestamp.isoformat() if conv.timestamp else None,
'error_type': error_type,
'error_message': error_message,
'model': 'qwen-turbo', # 实际使用的模型
'user_id': f'user_{conv.id}'
'model': 'qwen-turbo',
'user_id': f'user_{conv.id}',
'user_message': (conv.user_message or '')[:100],
'assistant_response': (conv.assistant_response or '')[:200],
'confidence_score': conv.confidence_score,
'response_time': conv.response_time,
})
error_id += 1
return jsonify({
'success': True,
@@ -476,6 +478,31 @@ def get_error_log():
except Exception as e:
return jsonify({"error": str(e)}), 500
@monitoring_bp.route('/ai-monitor/error-log/<int:conv_id>')
def get_error_detail(conv_id):
"""获取单条错误详情"""
try:
with db_manager.get_session() as session:
conv = session.query(Conversation).filter_by(id=conv_id).first()
if not conv:
return jsonify({"error": "记录不存在"}), 404
return jsonify({
'success': True,
'detail': {
'id': conv.id,
'timestamp': conv.timestamp.isoformat() if conv.timestamp else None,
'user_message': conv.user_message,
'assistant_response': conv.assistant_response,
'confidence_score': conv.confidence_score,
'response_time': conv.response_time,
'category': conv.category,
'source': conv.source,
}
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@monitoring_bp.route('/ai-monitor/error-log', methods=['DELETE'])
def clear_error_log():
"""清空错误日志"""

View File

@@ -3863,6 +3863,44 @@ class TSPDashboard {
}
}
async viewErrorDetail(convId) {
const modal = new bootstrap.Modal(document.getElementById('errorDetailModal'));
const body = document.getElementById('errorDetailBody');
body.innerHTML = '<div class="text-center text-muted"><i class="fas fa-spinner fa-spin me-2"></i>加载中...</div>';
modal.show();
try {
const response = await fetch(`/api/ai-monitor/error-log/${convId}`);
const data = await response.json();
if (data.success) {
const d = data.detail;
body.innerHTML = `
<table class="table table-bordered mb-0">
<tr><th style="width:120px">记录ID</th><td>${d.id}</td></tr>
<tr><th>时间</th><td>${d.timestamp ? new Date(d.timestamp).toLocaleString() : '-'}</td></tr>
<tr><th>分类</th><td>${d.category || '-'}</td></tr>
<tr><th>来源</th><td>${d.source || '-'}</td></tr>
<tr><th>置信度</th><td>${d.confidence_score != null ? d.confidence_score : '-'}</td></tr>
<tr><th>响应时间</th><td>${d.response_time != null ? d.response_time + ' ms' : '-'}</td></tr>
<tr><th>用户消息</th><td><pre class="mb-0" style="white-space:pre-wrap">${this.escapeHtml(d.user_message || '-')}</pre></td></tr>
<tr><th>助手回复</th><td><pre class="mb-0" style="white-space:pre-wrap">${this.escapeHtml(d.assistant_response || '-')}</pre></td></tr>
</table>
`;
} else {
body.innerHTML = `<div class="alert alert-danger">${data.error || '加载失败'}</div>`;
}
} catch (error) {
body.innerHTML = `<div class="alert alert-danger">请求失败: ${error.message}</div>`;
}
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 系统优化
async loadSystemOptimizer() {
try {

View File

@@ -2469,6 +2469,24 @@
<!-- 通知容器 -->
<div id="notificationContainer" class="position-fixed top-0 end-0 p-3" style="z-index: 1050;"></div>
<!-- 错误详情模态框 -->
<div class="modal fade" id="errorDetailModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-bug me-2"></i>错误详情</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="errorDetailBody">
<div class="text-center text-muted"><i class="fas fa-spinner fa-spin me-2"></i>加载中...</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- 脚本 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>