Files
Agent-Intent/intent/loader.go
weichen b58595fb38 Implement the intent core
Details (original message):
Implement the intent core, conformance suite, catalog alignment, examples, and the intentctl diagnostics CLI.
2026-09-29 15:35:18 +00:00

81 lines
2.3 KiB
Go

package intent
import (
"bytes"
"encoding/json"
"fmt"
"io/fs"
"path"
"sort"
)
// overlayDoc 是 JSON 配置文件的顶层结构。
//
// {
// "intents": [ { ...IntentSpec... } ],
// "disable": [ "demo.run.status_query" ]
// }
//
// intents 内同 id 条目覆盖内置或先前定义(version 必须递增);disable 按id禁用
// (保护域内的 id 会整批失败)。目录 root 内按文件名字典序加载,roots 按给定顺序应用。
type overlayDoc struct {
Intents []IntentSpec `json:"intents"`
Disable []string `json:"disable"`
}
// overlayEntry 单条 overlay 指令,source 定位到文件与下标,供错误与诊断使用。
type overlayEntry struct {
disable bool
id string
spec IntentSpec
source string
}
// loadOverlays 从 fsys 读取全部 roots。root 可以是目录(加载其中 *.json,字典序)
// 或单个文件路径。任何读取、解析或未知字段错误都会带来源返回。
func loadOverlays(fsys fs.FS, roots []string) ([]overlayEntry, error) {
var entries []overlayEntry
for _, root := range roots {
root = path.Clean(root)
files, err := overlayFiles(fsys, root)
if err != nil {
return nil, newError(LoadFailed, "读取配置 root 失败", "root", root, "error", err.Error())
}
for _, f := range files {
data, err := fs.ReadFile(fsys, f)
if err != nil {
return nil, newError(LoadFailed, "读取配置文件失败", "file", f, "error", err.Error())
}
var doc overlayDoc
dec := json.NewDecoder(bytes.NewReader(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&doc); err != nil {
return nil, newError(InvalidSpec, "配置解析失败(含未知字段)", "file", f, "error", err.Error())
}
for i := range doc.Intents {
entries = append(entries, overlayEntry{spec: doc.Intents[i], source: fmt.Sprintf("%s#intents[%d]", f, i)})
}
for i, id := range doc.Disable {
entries = append(entries, overlayEntry{disable: true, id: id, source: fmt.Sprintf("%s#disable[%d]", f, i)})
}
}
}
return entries, nil
}
func overlayFiles(fsys fs.FS, root string) ([]string, error) {
st, err := fs.Stat(fsys, root)
if err != nil {
return nil, err
}
if !st.IsDir() {
return []string{root}, nil
}
matches, err := fs.Glob(fsys, path.Join(root, "*.json"))
if err != nil {
return nil, err
}
sort.Strings(matches)
return matches, nil
}