diff --git a/internal/agent/agent.go b/internal/agent/agent.go index bfe1938f..d1a59c23 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -316,16 +316,16 @@ type ProgressCallback func(eventType, message string, data interface{}) // AgentLoop 执行Agent循环 func (a *Agent) AgentLoop(ctx context.Context, userInput string, historyMessages []ChatMessage) (*AgentLoopResult, error) { - return a.AgentLoopWithProgress(ctx, userInput, historyMessages, "", nil, nil, nil) + return a.AgentLoopWithProgress(ctx, userInput, historyMessages, "", nil, nil) } // AgentLoopWithConversationID 执行Agent循环(带对话ID) func (a *Agent) AgentLoopWithConversationID(ctx context.Context, userInput string, historyMessages []ChatMessage, conversationID string) (*AgentLoopResult, error) { - return a.AgentLoopWithProgress(ctx, userInput, historyMessages, conversationID, nil, nil, nil) + return a.AgentLoopWithProgress(ctx, userInput, historyMessages, conversationID, nil, nil) } -// EinoSingleAgentSystemInstruction 供 Eino adk.ChatModelAgent.Instruction 使用,与 AgentLoopWithProgress 首条 system 对齐(含 system_prompt_path 与 Skills 提示)。 -func (a *Agent) EinoSingleAgentSystemInstruction(roleSkills []string) string { +// EinoSingleAgentSystemInstruction 供 Eino adk.ChatModelAgent.Instruction 使用,与 AgentLoopWithProgress 首条 system 对齐(含 system_prompt_path)。 +func (a *Agent) EinoSingleAgentSystemInstruction() string { systemPrompt := DefaultSingleAgentSystemPrompt() if a.agentConfig != nil { if p := strings.TrimSpace(a.agentConfig.SystemPromptPath); p != "" { @@ -343,30 +343,11 @@ func (a *Agent) EinoSingleAgentSystemInstruction(roleSkills []string) string { } } } - if len(roleSkills) > 0 { - var skillsHint strings.Builder - skillsHint.WriteString("\n\n本角色推荐使用的Skills:\n") - for i, skillName := range roleSkills { - if i > 0 { - skillsHint.WriteString("、") - } - skillsHint.WriteString("`") - skillsHint.WriteString(skillName) - skillsHint.WriteString("`") - } - skillsHint.WriteString("\n- 这些名称与 skills/ 下 SKILL.md 的 `name` 一致。") - skillsHint.WriteString("\n- 若当前会话已启用 Eino 内置 `skill` 工具,请按需加载;否则以 MCP 与文本工作流完成。") - skillsHint.WriteString("\n- 例如传入 skill 参数为 `") - skillsHint.WriteString(roleSkills[0]) - skillsHint.WriteString("`") - systemPrompt += skillsHint.String() - } return systemPrompt } // AgentLoopWithProgress 执行Agent循环(带进度回调和对话ID) -// roleSkills: 角色配置的skills列表(用于在系统提示词中提示AI,但不硬编码内容) -func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, historyMessages []ChatMessage, conversationID string, callback ProgressCallback, roleTools []string, roleSkills []string) (*AgentLoopResult, error) { +func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, historyMessages []ChatMessage, conversationID string, callback ProgressCallback, roleTools []string) (*AgentLoopResult, error) { // 设置当前对话ID a.mu.Lock() a.currentConversationID = conversationID @@ -396,26 +377,6 @@ func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, his } } - // 如果角色配置了skills,在系统提示词中提示AI(但不硬编码内容) - if len(roleSkills) > 0 { - var skillsHint strings.Builder - skillsHint.WriteString("\n\n本角色推荐使用的Skills:\n") - for i, skillName := range roleSkills { - if i > 0 { - skillsHint.WriteString("、") - } - skillsHint.WriteString("`") - skillsHint.WriteString(skillName) - skillsHint.WriteString("`") - } - skillsHint.WriteString("\n- 这些名称与 skills/ 下 SKILL.md 的 `name` 一致;在 **Eino 多代理** 会话中请用内置 `skill` 工具按需加载全文") - skillsHint.WriteString("\n- 例如:在支持 Eino skill 工具时传入 skill 参数为 `") - skillsHint.WriteString(roleSkills[0]) - skillsHint.WriteString("`") - skillsHint.WriteString("\n- 单代理 MCP 模式不会注入 skill 工具;需要时请使用多代理(DeepAgent)") - systemPrompt += skillsHint.String() - } - messages := []ChatMessage{ { Role: "system", diff --git a/internal/app/app.go b/internal/app/app.go index 6128150f..cb5c031c 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -327,7 +327,6 @@ func New(cfg *config.Config, log *logger.Logger) (*App, error) { configHandler := handler.NewConfigHandler(configPath, cfg, mcpServer, executor, agent, attackChainHandler, externalMCPMgr, log.Logger) externalMCPHandler := handler.NewExternalMCPHandler(externalMCPMgr, cfg, configPath, log.Logger) roleHandler := handler.NewRoleHandler(cfg, configPath, log.Logger) - roleHandler.SetSkillsManager(skillpackage.DirLister{SkillsRoot: skillsDir}) skillsHandler := handler.NewSkillsHandler(cfg, configPath, log.Logger) fofaHandler := handler.NewFofaHandler(cfg, log.Logger) terminalHandler := handler.NewTerminalHandler(log.Logger) @@ -881,7 +880,6 @@ func setupRoutes( // 角色管理 protected.GET("/roles", roleHandler.GetRoles) protected.GET("/roles/:name", roleHandler.GetRole) - protected.GET("/roles/skills/list", roleHandler.GetSkills) protected.POST("/roles", roleHandler.CreateRole) protected.PUT("/roles/:name", roleHandler.UpdateRole) protected.DELETE("/roles/:name", roleHandler.DeleteRole) diff --git a/internal/handler/agent.go b/internal/handler/agent.go index 77614bbd..0ee4185b 100644 --- a/internal/handler/agent.go +++ b/internal/handler/agent.go @@ -494,8 +494,7 @@ func (h *AgentHandler) AgentLoop(c *gin.Context) { // 应用角色用户提示词和工具配置 finalMessage := req.Message - var roleTools []string // 角色配置的工具列表 - var roleSkills []string // 角色配置的skills列表(用于提示AI,但不硬编码内容) + var roleTools []string // 角色配置的工具列表 // WebShell AI 助手模式:绑定当前连接,仅开放 webshell_* 工具并注入 connection_id if req.WebShellConnectionID != "" { @@ -531,7 +530,6 @@ func (h *AgentHandler) AgentLoop(c *gin.Context) { builtin.ToolListKnowledgeRiskTypes, builtin.ToolSearchKnowledgeBase, } - roleSkills = nil } else if req.Role != "" && req.Role != "默认" { if h.config.Roles != nil { if role, exists := h.config.Roles[req.Role]; exists && role.Enabled { @@ -545,11 +543,6 @@ func (h *AgentHandler) AgentLoop(c *gin.Context) { roleTools = role.Tools h.logger.Info("使用角色配置的工具列表", zap.String("role", req.Role), zap.Int("toolCount", len(roleTools))) } - // 获取角色配置的skills列表(用于在系统提示词中提示AI,但不硬编码内容) - if len(role.Skills) > 0 { - roleSkills = role.Skills - h.logger.Info("角色配置了skills,将在系统提示词中提示AI", zap.String("role", req.Role), zap.Int("skillCount", len(roleSkills)), zap.Strings("skills", roleSkills)) - } } } } @@ -574,8 +567,7 @@ func (h *AgentHandler) AgentLoop(c *gin.Context) { } // 执行Agent Loop,传入历史消息和对话ID(使用包含角色提示词的finalMessage和角色工具列表) - // 注意:skills不会硬编码注入,但会在系统提示词中提示AI这个角色推荐使用哪些skills - result, err := h.agent.AgentLoopWithProgress(c.Request.Context(), finalMessage, agentHistoryMessages, conversationID, nil, roleTools, roleSkills) + result, err := h.agent.AgentLoopWithProgress(c.Request.Context(), finalMessage, agentHistoryMessages, conversationID, nil, roleTools) if err != nil { h.logger.Error("Agent Loop执行失败", zap.Error(err)) @@ -646,14 +638,13 @@ func (h *AgentHandler) ProcessMessageForRobot(ctx context.Context, conversationI } finalMessage := message - var roleTools, roleSkills []string + var roleTools []string if role != "" && role != "默认" && h.config.Roles != nil { if r, exists := h.config.Roles[role]; exists && r.Enabled { if r.UserPrompt != "" { finalMessage = r.UserPrompt + "\n\n" + message } roleTools = r.Tools - roleSkills = r.Skills } } @@ -720,7 +711,7 @@ func (h *AgentHandler) ProcessMessageForRobot(ctx context.Context, conversationI return resultMA.Response, conversationID, nil } - result, err := h.agent.AgentLoopWithProgress(ctx, finalMessage, agentHistoryMessages, conversationID, progressCallback, roleTools, roleSkills) + result, err := h.agent.AgentLoopWithProgress(ctx, finalMessage, agentHistoryMessages, conversationID, progressCallback, roleTools) if err != nil { errMsg := "执行失败: " + err.Error() if assistantMessageID != "" { @@ -1263,7 +1254,6 @@ func (h *AgentHandler) AgentLoopStream(c *gin.Context) { // 应用角色用户提示词和工具配置 finalMessage := req.Message var roleTools []string // 角色配置的工具列表 - var roleSkills []string if req.WebShellConnectionID != "" { conn, errConn := h.db.GetWebshellConnection(strings.TrimSpace(req.WebShellConnectionID)) if errConn != nil || conn == nil { @@ -1314,11 +1304,6 @@ func (h *AgentHandler) AgentLoopStream(c *gin.Context) { // 因为mcps是MCP服务器名称,不是工具列表 h.logger.Info("角色配置使用旧的mcps字段,将使用所有工具", zap.String("role", req.Role)) } - // 注意:角色 skills 仅在系统提示词中提示;运行时加载请使用 Eino 多代理内置 `skill` 工具 - if len(role.Skills) > 0 { - roleSkills = role.Skills - h.logger.Info("角色配置了skills,AI可通过工具按需调用", zap.String("role", req.Role), zap.Int("skillCount", len(role.Skills)), zap.Strings("skills", role.Skills)) - } } } } @@ -1423,12 +1408,11 @@ func (h *AgentHandler) AgentLoopStream(c *gin.Context) { // 执行Agent Loop,传入独立的上下文,确保任务不会因客户端断开而中断(使用包含角色提示词的finalMessage和角色工具列表) sendEvent("progress", "正在分析您的请求...", nil) - // 注意:roleSkills 已在上方根据 req.Role 或 WebShell 模式设置 stopKeepalive := make(chan struct{}) go sseKeepalive(c, stopKeepalive, &sseWriteMu) defer close(stopKeepalive) - result, err := h.agent.AgentLoopWithProgress(taskCtx, finalMessage, agentHistoryMessages, conversationID, progressCallback, roleTools, roleSkills) + result, err := h.agent.AgentLoopWithProgress(taskCtx, finalMessage, agentHistoryMessages, conversationID, progressCallback, roleTools) if err != nil { h.logger.Error("Agent Loop执行失败", zap.Error(err)) cause := context.Cause(baseCtx) @@ -2242,8 +2226,7 @@ func (h *AgentHandler) executeBatchQueue(queueID string) { // 应用角色用户提示词和工具配置 finalMessage := task.Message - var roleTools []string // 角色配置的工具列表 - var roleSkills []string // 角色配置的skills列表(用于提示AI,但不硬编码内容) + var roleTools []string // 角色配置的工具列表 if queue.Role != "" && queue.Role != "默认" { if h.config.Roles != nil { if role, exists := h.config.Roles[queue.Role]; exists && role.Enabled { @@ -2257,11 +2240,6 @@ func (h *AgentHandler) executeBatchQueue(queueID string) { roleTools = role.Tools h.logger.Info("使用角色配置的工具列表", zap.String("queueId", queueID), zap.String("taskId", task.ID), zap.String("role", queue.Role), zap.Int("toolCount", len(roleTools))) } - // 获取角色配置的skills列表(用于在系统提示词中提示AI,但不硬编码内容) - if len(role.Skills) > 0 { - roleSkills = role.Skills - h.logger.Info("角色配置了skills,将在系统提示词中提示AI", zap.String("queueId", queueID), zap.String("taskId", task.ID), zap.String("role", queue.Role), zap.Int("skillCount", len(roleSkills)), zap.Strings("skills", roleSkills)) - } } } } @@ -2295,7 +2273,6 @@ func (h *AgentHandler) executeBatchQueue(queueID string) { // 存储取消函数,以便在取消队列时能够取消当前任务 h.batchTaskManager.SetTaskCancel(queueID, cancel) // 使用队列配置的角色工具列表(如果为空,表示使用所有工具) - // 注意:skills不会硬编码注入,但会在系统提示词中提示AI这个角色推荐使用哪些skills useBatchMulti := false useEinoSingle := false batchOrch := "deep" @@ -2326,10 +2303,10 @@ func (h *AgentHandler) executeBatchQueue(queueID string) { if h.config == nil { runErr = fmt.Errorf("服务器配置未加载") } else { - resultMA, runErr = multiagent.RunEinoSingleChatModelAgent(ctx, h.config, &h.config.MultiAgent, h.agent, h.logger, conversationID, finalMessage, []agent.ChatMessage{}, roleTools, roleSkills, progressCallback) + resultMA, runErr = multiagent.RunEinoSingleChatModelAgent(ctx, h.config, &h.config.MultiAgent, h.agent, h.logger, conversationID, finalMessage, []agent.ChatMessage{}, roleTools, progressCallback) } default: - result, runErr = h.agent.AgentLoopWithProgress(ctx, finalMessage, []agent.ChatMessage{}, conversationID, progressCallback, roleTools, roleSkills) + result, runErr = h.agent.AgentLoopWithProgress(ctx, finalMessage, []agent.ChatMessage{}, conversationID, progressCallback, roleTools) } // 任务执行完成,清理取消函数 h.batchTaskManager.SetTaskCancel(queueID, nil) diff --git a/internal/handler/config.go b/internal/handler/config.go index e889c779..05542567 100644 --- a/internal/handler/config.go +++ b/internal/handler/config.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path/filepath" + "sort" "strconv" "strings" "sync" @@ -305,6 +306,8 @@ func (h *ConfigHandler) GetTools(c *gin.Context) { h.mu.RLock() defer h.mu.RUnlock() + c.Header("Cache-Control", "no-store, no-cache, must-revalidate") + // 解析分页参数 page := 1 pageSize := 20 @@ -326,15 +329,26 @@ func (h *ConfigHandler) GetTools(c *gin.Context) { searchTermLower = strings.ToLower(searchTerm) } - // 解析状态筛选参数: "true" = 仅已启用, "false" = 仅已停用, "" = 全部 - enabledFilter := c.Query("enabled") + // 解析状态筛选: tool_filter=on|off(角色弹窗等优先,避免与网关/代理对 enabled 的特殊处理冲突) + // 兼容旧参数 enabled=true|false var filterEnabled *bool - if enabledFilter == "true" { + toolFilter := strings.TrimSpace(strings.ToLower(c.Query("tool_filter"))) + switch toolFilter { + case "on", "1", "true", "enabled": v := true filterEnabled = &v - } else if enabledFilter == "false" { + case "off", "0", "false", "disabled": v := false filterEnabled = &v + default: + enabledFilter := strings.TrimSpace(c.Query("enabled")) + if enabledFilter == "true" { + v := true + filterEnabled = &v + } else if enabledFilter == "false" { + v := false + filterEnabled = &v + } } // 解析角色参数,用于过滤工具并标注启用状态 @@ -521,6 +535,17 @@ func (h *ConfigHandler) GetTools(c *gin.Context) { // 注意:这里我们不直接过滤掉工具,而是保留所有工具,但通过 role_enabled 字段标注状态 // 这样前端可以显示所有工具,并标注哪些工具在当前角色中可用 + // 统一按名称排序后再分页,避免配置文件中顺序导致「全部」与「仅已启用」前几页看起来完全一致 + sort.SliceStable(allTools, func(i, j int) bool { + key := func(t ToolConfigInfo) string { + if t.IsExternal && t.ExternalMCP != "" { + return strings.ToLower(t.ExternalMCP + "::" + t.Name) + } + return strings.ToLower(t.Name) + } + return key(allTools[i]) < key(allTools[j]) + }) + total := len(allTools) // 统计已启用的工具数(在角色中的启用工具数) totalEnabled := 0 diff --git a/internal/handler/eino_single_agent.go b/internal/handler/eino_single_agent.go index 76d3c908..9b7feddc 100644 --- a/internal/handler/eino_single_agent.go +++ b/internal/handler/eino_single_agent.go @@ -151,7 +151,6 @@ func (h *AgentHandler) EinoSingleAgentLoopStream(c *gin.Context) { prep.FinalMessage, prep.History, prep.RoleTools, - prep.RoleSkills, progressCallback, ) @@ -255,7 +254,6 @@ func (h *AgentHandler) EinoSingleAgentLoop(c *gin.Context) { prep.FinalMessage, prep.History, prep.RoleTools, - prep.RoleSkills, progressCallback, ) if runErr != nil { diff --git a/internal/handler/multi_agent_prepare.go b/internal/handler/multi_agent_prepare.go index 36d52994..ca03f4a7 100644 --- a/internal/handler/multi_agent_prepare.go +++ b/internal/handler/multi_agent_prepare.go @@ -18,7 +18,6 @@ type multiAgentPrepared struct { History []agent.ChatMessage FinalMessage string RoleTools []string - RoleSkills []string AssistantMessageID string UserMessageID string } @@ -68,7 +67,6 @@ func (h *AgentHandler) prepareMultiAgentSession(req *ChatRequest) (*multiAgentPr finalMessage := req.Message var roleTools []string - var roleSkills []string if req.WebShellConnectionID != "" { conn, errConn := h.db.GetWebshellConnection(strings.TrimSpace(req.WebShellConnectionID)) if errConn != nil || conn == nil { @@ -107,7 +105,6 @@ func (h *AgentHandler) prepareMultiAgentSession(req *ChatRequest) (*multiAgentPr finalMessage = role.UserPrompt + "\n\n" + req.Message } roleTools = role.Tools - roleSkills = role.Skills } } @@ -146,7 +143,6 @@ func (h *AgentHandler) prepareMultiAgentSession(req *ChatRequest) (*multiAgentPr History: agentHistoryMessages, FinalMessage: finalMessage, RoleTools: roleTools, - RoleSkills: roleSkills, AssistantMessageID: assistantMessageID, UserMessageID: userMessageID, }, nil diff --git a/internal/handler/openapi.go b/internal/handler/openapi.go index bf27e396..cf082d9d 100644 --- a/internal/handler/openapi.go +++ b/internal/handler/openapi.go @@ -648,13 +648,6 @@ func (h *OpenAPIHandler) GetOpenAPISpec(c *gin.Context) { "type": "string", }, }, - "skills": map[string]interface{}{ - "type": "array", - "description": "Skills列表", - "items": map[string]interface{}{ - "type": "string", - }, - }, }, }, "Skill": map[string]interface{}{ @@ -2879,38 +2872,6 @@ func (h *OpenAPIHandler) GetOpenAPISpec(c *gin.Context) { }, }, }, - "/api/roles/skills/list": map[string]interface{}{ - "get": map[string]interface{}{ - "tags": []string{"角色管理"}, - "summary": "获取可用Skills列表", - "description": "获取所有可用的Skills列表,用于角色配置", - "operationId": "getSkills", - "responses": map[string]interface{}{ - "200": map[string]interface{}{ - "description": "获取成功", - "content": map[string]interface{}{ - "application/json": map[string]interface{}{ - "schema": map[string]interface{}{ - "type": "object", - "properties": map[string]interface{}{ - "skills": map[string]interface{}{ - "type": "array", - "description": "Skills列表", - "items": map[string]interface{}{ - "type": "string", - }, - }, - }, - }, - }, - }, - }, - "401": map[string]interface{}{ - "description": "未授权", - }, - }, - }, - }, "/api/skills": map[string]interface{}{ "get": map[string]interface{}{ "tags": []string{"Skills管理"}, diff --git a/internal/handler/role.go b/internal/handler/role.go index 88c42138..85411b19 100644 --- a/internal/handler/role.go +++ b/internal/handler/role.go @@ -18,15 +18,9 @@ import ( // RoleHandler 角色处理器 type RoleHandler struct { - config *config.Config - configPath string - logger *zap.Logger - skillsManager SkillsManager // Skills管理器接口(可选) -} - -// SkillsManager Skills管理器接口 -type SkillsManager interface { - ListSkills() ([]string, error) + config *config.Config + configPath string + logger *zap.Logger } // NewRoleHandler 创建新的角色处理器 @@ -38,34 +32,6 @@ func NewRoleHandler(cfg *config.Config, configPath string, logger *zap.Logger) * } } -// SetSkillsManager 设置Skills管理器 -func (h *RoleHandler) SetSkillsManager(manager SkillsManager) { - h.skillsManager = manager -} - -// GetSkills 获取所有可用的skills列表 -func (h *RoleHandler) GetSkills(c *gin.Context) { - if h.skillsManager == nil { - c.JSON(http.StatusOK, gin.H{ - "skills": []string{}, - }) - return - } - - skills, err := h.skillsManager.ListSkills() - if err != nil { - h.logger.Warn("获取skills列表失败", zap.Error(err)) - c.JSON(http.StatusOK, gin.H{ - "skills": []string{}, - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "skills": skills, - }) -} - // GetRoles 获取所有角色 func (h *RoleHandler) GetRoles(c *gin.Context) { if h.config.Roles == nil { diff --git a/internal/handler/skills.go b/internal/handler/skills.go index f6577292..09e5e0ff 100644 --- a/internal/handler/skills.go +++ b/internal/handler/skills.go @@ -308,31 +308,10 @@ func (h *SkillsHandler) GetSkillBoundRoles(c *gin.Context) { }) } -// getRolesBoundToSkill 获取绑定指定skill的角色列表(不修改配置) +// getRolesBoundToSkill 预留:角色不再配置 skill 绑定,始终返回空列表。 func (h *SkillsHandler) getRolesBoundToSkill(skillName string) []string { - if h.config.Roles == nil { - return []string{} - } - - boundRoles := make([]string, 0) - for roleName, role := range h.config.Roles { - // 确保角色名称正确设置 - if role.Name == "" { - role.Name = roleName - } - - // 检查角色的Skills列表中是否包含该skill - if len(role.Skills) > 0 { - for _, skill := range role.Skills { - if skill == skillName { - boundRoles = append(boundRoles, roleName) - break - } - } - } - } - - return boundRoles + _ = skillName + return nil } // CreateSkill 创建新 skill(标准 Agent Skills:生成 SKILL.md + YAML front matter) @@ -600,55 +579,10 @@ func (h *SkillsHandler) ClearSkillStatsByName(c *gin.Context) { }) } -// removeSkillFromRoles 从所有角色中移除指定的skill绑定 -// 返回受影响角色名称列表 +// removeSkillFromRoles 预留:角色不再存储 skill 绑定,无操作。 func (h *SkillsHandler) removeSkillFromRoles(skillName string) []string { - if h.config.Roles == nil { - return []string{} - } - - affectedRoles := make([]string, 0) - rolesToUpdate := make(map[string]config.RoleConfig) - - // 遍历所有角色,查找并移除skill绑定 - for roleName, role := range h.config.Roles { - // 确保角色名称正确设置 - if role.Name == "" { - role.Name = roleName - } - - // 检查角色的Skills列表中是否包含要删除的skill - if len(role.Skills) > 0 { - updated := false - newSkills := make([]string, 0, len(role.Skills)) - for _, skill := range role.Skills { - if skill != skillName { - newSkills = append(newSkills, skill) - } else { - updated = true - } - } - if updated { - role.Skills = newSkills - rolesToUpdate[roleName] = role - affectedRoles = append(affectedRoles, roleName) - } - } - } - - // 如果有角色需要更新,保存到文件 - if len(rolesToUpdate) > 0 { - // 更新内存中的配置 - for roleName, role := range rolesToUpdate { - h.config.Roles[roleName] = role - } - // 保存更新后的角色配置到文件 - if err := h.saveRolesConfig(); err != nil { - h.logger.Error("保存角色配置失败", zap.Error(err)) - } - } - - return affectedRoles + _ = skillName + return nil } // saveRolesConfig 保存角色配置到文件(从SkillsHandler调用) diff --git a/internal/skillpackage/layout.go b/internal/skillpackage/layout.go index 0da7395a..275e1924 100644 --- a/internal/skillpackage/layout.go +++ b/internal/skillpackage/layout.go @@ -33,12 +33,12 @@ func SkillsRootFromConfig(skillsDir string, configPath string) string { return skillsDir } -// DirLister satisfies handler.SkillsManager for role UI (lists package directory names). +// DirLister lists skill package directory names under SkillsRoot. type DirLister struct { SkillsRoot string } -// ListSkills implements the role handler dependency. +// ListSkills returns skill package directory names that contain SKILL.md. func (d DirLister) ListSkills() ([]string, error) { return ListSkillDirNames(d.SkillsRoot) }