Details (original message): Implement the intent core, conformance suite, catalog alignment, examples, and the intentctl diagnostics CLI.
87 lines
3.0 KiB
Go
87 lines
3.0 KiB
Go
// Package intent 提供通用的意图识别机制:意图定义(spec)、注册表与配置合并、
|
|
// 四级漏斗识别器(guard → expectation → rules → adjudicate)、槽位抽取与诊断。
|
|
//
|
|
// 本包不含任何业务意图内容;词表、正则与守卫规则一律由宿主以 Go 注册或 JSON 配置提供。
|
|
// 识别路径纯内存、确定性:同输入 + 同快照 → 同结果。「无匹配」(fallback)是正常
|
|
// 识别结果而非错误;错误只表示系统级失败(配置损坏、调用方参数不合法)。
|
|
package intent
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// 规范码常量。字符串值与 Error-Code-System 的 intent 域 / sys 域种子码一致,
|
|
// 由 catalogcheck 包的对齐测试防止两处漂移。
|
|
const (
|
|
// InvalidSpec 表示意图定义或配置校验失败:id 冲突、正则不合法、未知字段、
|
|
// matcher 缺少正向条件、槽位 group 越界、覆盖版本未递增等。整批加载已原子拒绝。
|
|
InvalidSpec = "intent.invalid_spec"
|
|
// SpecProtected 表示 overlay 试图覆盖或禁用保护域内的 spec。保护域由宿主构建时声明。
|
|
SpecProtected = "intent.spec_protected"
|
|
// LoadFailed 表示配置读取或解析失败。失败时保留上一生效快照。
|
|
LoadFailed = "intent.load_failed"
|
|
// InvalidArgument 复用框架域,表示调用方错误:nil 快照、输入超长。
|
|
InvalidArgument = "sys.invalid_argument"
|
|
)
|
|
|
|
// Error 是本模块的系统级错误。实现 ErrorCode / ErrorFields 鸭子方法,
|
|
// logging-system 的 logsys 识别后自动把码写入 code、字段并入 fields,无需互相依赖。
|
|
type Error struct {
|
|
Code string
|
|
Message string
|
|
Fields map[string]any
|
|
}
|
|
|
|
// Error 实现error接口。
|
|
func (e *Error) Error() string {
|
|
var b strings.Builder
|
|
b.WriteString("intent: ")
|
|
b.WriteString(e.Code)
|
|
b.WriteString(": ")
|
|
b.WriteString(e.Message)
|
|
keys := make([]string, 0, len(e.Fields))
|
|
for k := range e.Fields {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
fmt.Fprintf(&b, " %s=%v", k, e.Fields[k])
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
// ErrorCode 返回规范码,供日志与错误信封对齐。
|
|
func (e *Error) ErrorCode() string { return e.Code }
|
|
|
|
// ErrorFields 返回结构化定位字段(spec id、来源文件、字段路径等)。
|
|
func (e *Error) ErrorFields() map[string]any { return e.Fields }
|
|
|
|
func newError(code, message string, kv ...any) *Error {
|
|
return &Error{Code: code, Message: message, Fields: fieldsFrom(kv)}
|
|
}
|
|
|
|
func (e *Error) with(kv ...any) *Error {
|
|
merged := make(map[string]any, len(e.Fields)+len(kv)/2)
|
|
for k, v := range e.Fields {
|
|
merged[k] = v
|
|
}
|
|
for i := 0; i+1 < len(kv); i += 2 {
|
|
if k, ok := kv[i].(string); ok {
|
|
merged[k] = kv[i+1]
|
|
}
|
|
}
|
|
return &Error{Code: e.Code, Message: e.Message, Fields: merged}
|
|
}
|
|
|
|
func fieldsFrom(kv []any) map[string]any {
|
|
m := make(map[string]any, len(kv)/2)
|
|
for i := 0; i+1 < len(kv); i += 2 {
|
|
if k, ok := kv[i].(string); ok {
|
|
m[k] = kv[i+1]
|
|
}
|
|
}
|
|
return m
|
|
}
|