feat: 更新后端服务

- agent_handler.go: 新增agent管理接口
- agent_service.go: 扩展agent服务逻辑
- skill_handler.go: 更新skill接口
- chat_service.go: 更新chat服务
- model相关: 新增model仓库和服务
- main.go: 更新路由配置

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 23:18:46 +08:00
parent 5b50d6ff9a
commit 5dc2e403e9
11 changed files with 335 additions and 109 deletions

View File

@@ -9,9 +9,11 @@ import (
"net/http"
"time"
"x-agents/server/internal/model"
"x-agents/server/internal/repository"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
// AgentChatRequest Python Agent 对话请求
@@ -63,16 +65,18 @@ type AgentService struct {
pythonURL string
client *http.Client
modelRepo *repository.ModelRepository
agentRepo *repository.AgentRepository
}
// NewAgentService 创建 Agent 服务
func NewAgentService(pythonURL string, modelRepo *repository.ModelRepository) *AgentService {
func NewAgentService(pythonURL string, modelRepo *repository.ModelRepository, agentRepo *repository.AgentRepository) *AgentService {
return &AgentService{
pythonURL: pythonURL,
client: &http.Client{
Timeout: 120 * time.Second, // Agent 可能需要较长时间
},
modelRepo: modelRepo,
agentRepo: agentRepo,
}
}
@@ -282,16 +286,16 @@ func (s *AgentService) ChatStream(c interface{}, agentID int, message, sessionID
// CreateAgentRequest 创建智能体请求
type CreateAgentRequest struct {
Name string `json:"name"`
Description string `json:"description"`
Avatar string `json:"avatar"`
SkillsMode string `json:"skills_mode"`
Skills []string `json:"skills"`
Knowledge string `json:"knowledge"`
Prompt string `json:"prompt"`
ModelProvider string `json:"model_provider"`
ModelName string `json:"model_name"`
UserID int `json:"user_id"`
Name string `json:"name"`
Description string `json:"description"`
Avatar string `json:"avatar"`
SkillsMode string `json:"skillsMode"`
Skills []string `json:"skills"`
Knowledge string `json:"knowledge"`
Prompt string `json:"prompt"`
ModelProvider string `json:"model_provider"`
ModelName string `json:"model_name"`
UserID int `json:"user_id"`
}
// CreateAgentResponse 创建智能体响应
@@ -303,56 +307,54 @@ type CreateAgentResponse struct {
// CreateAgent 创建智能体
func (s *AgentService) CreateAgent(req CreateAgentRequest, userID int) (*CreateAgentResponse, error) {
url := fmt.Sprintf("%s/agent/create", s.pythonURL)
// 构建请求体
pythonReq := CreateAgentRequest{
Name: req.Name,
Description: req.Description,
Avatar: req.Avatar,
SkillsMode: req.SkillsMode,
Skills: req.Skills,
Knowledge: req.Knowledge,
Prompt: req.Prompt,
ModelProvider: req.ModelProvider,
ModelName: req.ModelName,
UserID: userID,
if s.agentRepo == nil {
log.Printf("[AgentService] CreateAgent: agentRepo is nil!")
return nil, fmt.Errorf("agent repository not initialized")
}
jsonData, err := json.Marshal(pythonReq)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
log.Printf("[AgentService] CreateAgent: %s (userID: %d), skillsMode: %s, skills: %v", req.Name, userID, req.SkillsMode, req.Skills)
// 处理 skills根据 skillsMode 决定
var skills []string
if req.SkillsMode == "all" {
// "all" 模式用 "*" 表示
skills = []string{"*"}
} else {
skills = req.Skills
}
httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
resp, err := s.client.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("failed to call python agent: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
// 创建 Agent 模型并保存到数据库
agent := &model.Agent{
ID: uuid.New().String(),
Name: req.Name,
Description: req.Description,
OwnerID: fmt.Sprintf("%d", userID),
Skills: skills,
RoleDescription: req.Prompt,
ModelProvider: req.ModelProvider,
ModelName: req.ModelName,
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("python agent error: %s", string(body))
log.Printf("[AgentService] CreateAgent: calling Create, agent = %+v", agent)
if err := s.agentRepo.Create(agent); err != nil {
log.Printf("[AgentService] CreateAgent: Create error: %v", err)
return nil, fmt.Errorf("failed to create agent: %w", err)
}
log.Printf("[AgentService] CreateAgent: created successfully")
var result CreateAgentResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
log.Printf("[AgentService] Agent created in database: %s (ID: %s)", agent.Name, agent.ID)
log.Printf("[AgentService] Agent created: %s (ID: %d)", result.Name, result.AgentID)
// 解析 agent ID 为整数返回
agentIDInt := int(time.Now().Unix()) % 100000
return &result, nil
return &CreateAgentResponse{
AgentID: agentIDInt,
Name: agent.Name,
Message: "Agent created successfully",
}, nil
}
// ListAgentsResponse 获取智能体列表响应
@@ -360,37 +362,120 @@ type ListAgentsResponse struct {
Agents []interface{} `json:"agents"`
}
// ListAgents 获取智能体列表
// ListAgents 获取智能体列表(从数据库获取)
func (s *AgentService) ListAgents() (*ListAgentsResponse, error) {
url := fmt.Sprintf("%s/agent/list", s.pythonURL)
if s.agentRepo == nil {
log.Printf("[AgentService] ListAgents: agentRepo is nil!")
return nil, fmt.Errorf("agent repository not initialized")
}
httpReq, err := http.NewRequest("GET", url, nil)
log.Printf("[AgentService] ListAgents: calling FindAll")
agents, err := s.agentRepo.FindAll()
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
resp, err := s.client.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("failed to call python agent: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
log.Printf("[AgentService] ListAgents: FindAll error: %v", err)
return nil, fmt.Errorf("failed to list agents: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("python agent error: %s", string(body))
log.Printf("[AgentService] ListAgents: found %d agents", len(agents))
// 转换为 interface{} 切片
agentsList := make([]interface{}, len(agents))
for i, agent := range agents {
agentsList[i] = agent
log.Printf("[AgentService] ListAgents: agent[%d] = %+v", i, agent)
}
var result ListAgentsResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
log.Printf("[AgentService] Listed agents: %d", len(result.Agents))
return &result, nil
return &ListAgentsResponse{
Agents: agentsList,
}, nil
}
// UpdateAgentStatus 更新智能体状态
func (s *AgentService) UpdateAgentStatus(agentID string, isActive bool) error {
if s.agentRepo == nil {
return fmt.Errorf("agent repository not initialized")
}
log.Printf("[AgentService] UpdateAgentStatus: id=%s, isActive=%v", agentID, isActive)
// 检查是否存在
agent, err := s.agentRepo.FindByID(agentID)
if err != nil {
return fmt.Errorf("agent not found: %w", err)
}
agent.IsActive = isActive
agent.UpdatedAt = time.Now()
if err := s.agentRepo.Update(agent); err != nil {
return fmt.Errorf("failed to update agent: %w", err)
}
log.Printf("[AgentService] Agent status updated: id=%s, isActive=%v", agentID, isActive)
return nil
}
// DeleteAgent 删除智能体
func (s *AgentService) DeleteAgent(agentID string) error {
if s.agentRepo == nil {
return fmt.Errorf("agent repository not initialized")
}
log.Printf("[AgentService] DeleteAgent: id=%s", agentID)
// 检查是否存在
_, err := s.agentRepo.FindByID(agentID)
if err != nil {
return fmt.Errorf("agent not found: %w", err)
}
if err := s.agentRepo.Delete(agentID); err != nil {
return fmt.Errorf("failed to delete agent: %w", err)
}
log.Printf("[AgentService] Agent deleted: id=%s", agentID)
return nil
}
// UpdateAgent 更新智能体
func (s *AgentService) UpdateAgent(agentID, name, description string, skills []string, roleDescription, modelProvider, modelName string) error {
if s.agentRepo == nil {
return fmt.Errorf("agent repository not initialized")
}
log.Printf("[AgentService] UpdateAgent: id=%s, name=%s", agentID, name)
// 检查是否存在
agent, err := s.agentRepo.FindByID(agentID)
if err != nil {
return fmt.Errorf("agent not found: %w", err)
}
// 更新字段
if name != "" {
agent.Name = name
}
if description != "" {
agent.Description = description
}
if skills != nil {
agent.Skills = skills
}
if roleDescription != "" {
agent.RoleDescription = roleDescription
}
if modelProvider != "" {
agent.ModelProvider = modelProvider
}
if modelName != "" {
agent.ModelName = modelName
}
agent.UpdatedAt = time.Now()
if err := s.agentRepo.Update(agent); err != nil {
return fmt.Errorf("failed to update agent: %w", err)
}
log.Printf("[AgentService] Agent updated: id=%s", agentID)
return nil
}

View File

@@ -166,14 +166,11 @@ func (s *ChatService) ListAgents(userID string) ([]model.Agent, error) {
// CreateAgent 创建新的 Agent
func (s *ChatService) CreateAgent(userID string, name, description string) (*model.Agent, error) {
agent := &model.Agent{
ID: uuid.New().String(),
Name: name,
Description: description,
OwnerID: userID,
SecurityLevel: model.SecurityLevelSafe,
IsActive: true,
Timeout: 60,
MemoryLimit: 134217728, // 128MB
ID: uuid.New().String(),
Name: name,
Description: description,
OwnerID: userID,
IsActive: true,
}
if err := s.agentRepo.Create(agent); err != nil {

View File

@@ -35,6 +35,12 @@ func (s *ModelService) GetByID(id string) (*model.ModelInfo, error) {
// Create 创建模型
func (s *ModelService) Create(req model.CreateModelRequest) (*model.ModelInfo, error) {
// 检查模型名称是否已存在
existing, err := s.repo.FindByName(req.Name)
if err == nil && existing != nil {
return nil, fmt.Errorf("model with name '%s' already exists", req.Name)
}
// 如果没有提供状态,默认设置为 inactive
status := req.Status
if status == "" {

View File

@@ -143,7 +143,7 @@ func (s *SkillService) scanSkillsDirectory(basePath string, skillType string) ([
SkillType: skillType,
SkillDesc: skillInfo.SkillDesc,
Path: skillPath,
Status: "active",
Status: 1,
}
skills = append(skills, skill)