feat: Day 10-11 - Agent Configuration System completed
Backend: - Create agents.yaml config file with 12 agents definition - Create Prompt templates for topic-evaluation agent - Implement agentService.ts for loading and managing agent configs - Create agentController.ts with CRUD operations - Create agent routes (GET /agents, /agents/:id, etc.) - Register agent routes in main server Frontend: - Create agentApi.ts service module - Update AgentChatPage to dynamically load agent config from API - Add loading state and error handling - Display agent details (description, category, model) Build: Both frontend and backend build successfully
This commit is contained in:
10
frontend/package-lock.json
generated
10
frontend/package-lock.json
generated
@@ -9,8 +9,10 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.5.2",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"antd": "^5.22.5",
|
||||
"axios": "^1.7.9",
|
||||
"js-yaml": "^4.1.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.28.0"
|
||||
@@ -1788,6 +1790,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/js-yaml": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/@types/js-yaml/-/js-yaml-4.0.9.tgz",
|
||||
"integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@@ -2245,7 +2253,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
@@ -3577,7 +3584,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.28.0",
|
||||
"@ant-design/icons": "^5.5.2",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"antd": "^5.22.5",
|
||||
"axios": "^1.7.9",
|
||||
"@ant-design/icons": "^5.5.2"
|
||||
"js-yaml": "^4.1.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.28.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.18",
|
||||
@@ -33,4 +35,3 @@
|
||||
"vite": "^6.0.7"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
frontend/src/api/agentApi.ts
Normal file
77
frontend/src/api/agentApi.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import request from './request';
|
||||
|
||||
export interface AgentConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
description: string;
|
||||
category: string;
|
||||
icon: string;
|
||||
enabled: boolean;
|
||||
systemPromptFile: string;
|
||||
userPromptTemplateFile: string;
|
||||
models: {
|
||||
[modelName: string]: {
|
||||
temperature: number;
|
||||
maxTokens: number;
|
||||
topP?: number;
|
||||
};
|
||||
};
|
||||
ragEnabled: boolean;
|
||||
requiresProject: boolean;
|
||||
outputFormat: 'text' | 'structured' | 'document';
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export interface ApiResponse<T = any> {
|
||||
success: boolean;
|
||||
data?: T;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const agentApi = {
|
||||
// 获取所有智能体列表
|
||||
getAll: async (): Promise<ApiResponse<AgentConfig[]>> => {
|
||||
const response = await request.get('/agents');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 获取启用的智能体列表
|
||||
getEnabled: async (): Promise<ApiResponse<AgentConfig[]>> => {
|
||||
const response = await request.get('/agents/enabled');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 获取单个智能体详情
|
||||
getById: async (id: string): Promise<ApiResponse<AgentConfig>> => {
|
||||
const response = await request.get(`/agents/${id}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 根据分类获取智能体
|
||||
getByCategory: async (category: string): Promise<ApiResponse<AgentConfig[]>> => {
|
||||
const response = await request.get(`/agents/by-category?category=${encodeURIComponent(category)}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 获取智能体的系统Prompt
|
||||
getSystemPrompt: async (id: string): Promise<ApiResponse<{ agentId: string; systemPrompt: string }>> => {
|
||||
const response = await request.get(`/agents/${id}/system-prompt`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 渲染用户Prompt
|
||||
renderPrompt: async (
|
||||
id: string,
|
||||
data: {
|
||||
projectBackground?: string;
|
||||
userInput: string;
|
||||
knowledgeBaseContext?: string;
|
||||
}
|
||||
): Promise<ApiResponse<{ agentId: string; renderedPrompt: string }>> => {
|
||||
const response = await request.post(`/agents/${id}/render-prompt`, data);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { Card, Typography, Input, Button, Space, Select, Upload, Tag, Alert, Divider } from 'antd'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Card, Typography, Input, Button, Space, Select, Upload, Tag, Alert, Divider, Spin } from 'antd'
|
||||
import {
|
||||
SendOutlined,
|
||||
PaperClipOutlined,
|
||||
@@ -7,20 +8,57 @@ import {
|
||||
FolderOpenOutlined,
|
||||
SyncOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { AGENTS } from '../layouts/MainLayout'
|
||||
import { agentApi, type AgentConfig } from '../api/agentApi'
|
||||
import { message } from 'antd'
|
||||
|
||||
const { Title, Paragraph } = Typography
|
||||
const { TextArea } = Input
|
||||
|
||||
const AgentChatPage = () => {
|
||||
const { agentId } = useParams()
|
||||
const agent = AGENTS.find((a) => a.id === agentId)
|
||||
const [agent, setAgent] = useState<AgentConfig | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
if (!agent) {
|
||||
// 加载智能体配置
|
||||
useEffect(() => {
|
||||
const fetchAgent = async () => {
|
||||
if (!agentId) return
|
||||
|
||||
try {
|
||||
setLoading(true)
|
||||
const response = await agentApi.getById(agentId)
|
||||
|
||||
if (response.success && response.data) {
|
||||
setAgent(response.data)
|
||||
} else {
|
||||
setError(response.message || '智能体不存在')
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load agent:', err)
|
||||
setError('加载智能体配置失败')
|
||||
message.error('加载智能体配置失败')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
fetchAgent()
|
||||
}, [agentId])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ textAlign: 'center', padding: '100px 0' }}>
|
||||
<Spin size="large" tip="加载智能体配置中..." />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error || !agent) {
|
||||
return (
|
||||
<Alert
|
||||
message="智能体不存在"
|
||||
description="请从首页选择一个智能体"
|
||||
description={error || "请从首页选择一个智能体"}
|
||||
type="error"
|
||||
showIcon
|
||||
/>
|
||||
@@ -49,7 +87,10 @@ const AgentChatPage = () => {
|
||||
{agent.name}
|
||||
</Title>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
|
||||
当前模型:DeepSeek-V3
|
||||
{agent.description}
|
||||
</Paragraph>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 0, fontSize: 12 }}>
|
||||
当前模型:DeepSeek-V3 | 分类:{agent.category}
|
||||
</Paragraph>
|
||||
</div>
|
||||
</Space>
|
||||
|
||||
Reference in New Issue
Block a user