77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
|
|
package main
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"os"
|
|||
|
|
"strings"
|
|||
|
|
|
|||
|
|
"gopkg.in/yaml.v3"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// LoadAgent 从 .md 文件加载 agent 定义
|
|||
|
|
// 搜索结果:项目目录 → 全局配置目录
|
|||
|
|
func LoadAgent(name string) (*AgentDef, error) {
|
|||
|
|
path := SearchFile(name)
|
|||
|
|
data, err := os.ReadFile(path)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("读取 agent 文件失败 (搜索路径: %s): %w", name, err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
content := string(data)
|
|||
|
|
frontmatter, body, err := parseFrontmatter(content)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def := &AgentDef{SystemPrompt: strings.TrimSpace(body)}
|
|||
|
|
if err := yaml.Unmarshal([]byte(frontmatter), def); err != nil {
|
|||
|
|
return nil, fmt.Errorf("解析 frontmatter 失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if def.Name == "" {
|
|||
|
|
return nil, fmt.Errorf("agent 定义缺少 name 字段")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 注入能力边界目录到 system prompt
|
|||
|
|
def.SystemPrompt += BuildInjectPrompt(def.Tools)
|
|||
|
|
|
|||
|
|
return def, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func parseFrontmatter(content string) (string, string, error) {
|
|||
|
|
lines := strings.Split(content, "\n")
|
|||
|
|
if len(lines) < 2 || strings.TrimSpace(lines[0]) != "---" {
|
|||
|
|
return "", content, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
endIdx := -1
|
|||
|
|
for i := 1; i < len(lines); i++ {
|
|||
|
|
if strings.TrimSpace(lines[i]) == "---" {
|
|||
|
|
endIdx = i
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if endIdx == -1 {
|
|||
|
|
return "", content, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
frontmatter := strings.Join(lines[1:endIdx], "\n")
|
|||
|
|
body := strings.Join(lines[endIdx+1:], "\n")
|
|||
|
|
return frontmatter, body, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// LoadSkill 按名称加载 skill 知识内容
|
|||
|
|
// 搜索结果:skills/<name>/SKILL.md → ~/.config/weather-cli/skills/<name>/SKILL.md
|
|||
|
|
func LoadSkill(name string) (string, error) {
|
|||
|
|
relativePath := fmt.Sprintf("skills/%s/SKILL.md", name)
|
|||
|
|
path := SearchFile(relativePath)
|
|||
|
|
|
|||
|
|
data, err := os.ReadFile(path)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("skill %q 未找到", name)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_, body, _ := parseFrontmatter(string(data))
|
|||
|
|
return strings.TrimSpace(body), nil
|
|||
|
|
}
|