package core import "encoding/json" // 智能体画像(4.7):核心定制机制,全部数据化、可导入导出。 type AgentProfile struct { ID string `json:"id"` Owner string `json:"owner,omitempty"` // 租户;空 = 共享(builtin) Name string `json:"name"` Description string `json:"description,omitempty"` Builtin bool `json:"builtin,omitempty"` Source string `json:"source,omitempty"` // builtin | plugin | user SystemPrompt string `json:"systemPrompt"` // PromptModules 引用提示词库模块 ID(有序;空 = 组装默认基座全集)。 // SystemPrompt 兼容保留:非空时作为附加段追加在模块组装结果之后。 PromptModules []string `json:"promptModules,omitempty"` Model ModelRoute `json:"model"` Tools ToolPolicy `json:"tools"` Context ContextPolicy `json:"context"` HITL HITLPolicy `json:"hitl"` Budget RunBudget `json:"budget"` } // ModelRoute 按用途选择模型(4.7 kind 路由):空串回落到 chat 默认。 type ModelRoute struct { Chat string `json:"chat,omitempty"` Lightweight string `json:"lightweight,omitempty"` Embedding string `json:"embedding,omitempty"` Rerank string `json:"rerank,omitempty"` } // ToolPolicy 三清单:allow/deny 决定可见工具,confirm 强制执行前 HITL 确认。 // 匹配语义:精确名或前缀通配("http.*" 表示 http 前缀);deny 优先于 allow。 type ToolPolicy struct { Allow []string `json:"allow"` // ["*"] 全部 Deny []string `json:"deny,omitempty"` Confirm []string `json:"confirm,omitempty"` } // ContextPolicy(4.10):ctxasm 的输入;逐版本增加策略项不动组装器接口。 type ContextPolicy struct { MaxHistoryMessages int `json:"maxHistoryMessages"` // 0 = 默认 40 SummarizeBeyond bool `json:"summarizeBeyond,omitempty"` // 远期;先存标志 MemoryBudgetPct int `json:"memoryBudgetPct,omitempty"` // 注入槽份额上限 KnowledgeBudgetPct int `json:"knowledgeBudgetPct,omitempty"` MaxToolResultChars int `json:"maxToolResultChars,omitempty"` // 0 = 默认 20000 } type HITLPolicy struct { AskOnAmbiguity bool `json:"askOnAmbiguity"` TimeoutSec *int `json:"timeoutSec,omitempty"` } type RunBudget struct { MaxTokens *int `json:"maxTokens,omitempty"` MaxToolCalls *int `json:"maxToolCalls,omitempty"` MaxTurns *int `json:"maxTurns,omitempty"` // LLM 循环轮上限 } // ToolAllows 判定:deny 优先;allow 含 "*" 或精确/前缀命中。 func (p ToolPolicy) ToolAllowed(name string) bool { if matchAny(p.Deny, name) { return false } if len(p.Allow) == 0 { return true } return matchAny(p.Allow, name) } func (p ToolPolicy) NeedsConfirm(name string) bool { return matchAny(p.Confirm, name) } // matchAny 语义:pattern 精确等于 name,或以 "xxx." 开头表示前缀族(http. → http.*)。 func matchAny(patterns []string, name string) bool { for _, p := range patterns { if p == "*" || p == name { return true } if n := len(p); n > 1 && p[n-1] == '.' { if len(name) > n-1 && name[:n-1] == p[:n-1] { return true } } } return false } // ---- 设置(4.9)---- type SettingType string const ( SettingString SettingType = "string" SettingNumber SettingType = "number" SettingBool SettingType = "boolean" SettingEnum SettingType = "enum" SettingSecret SettingType = "secret" ) type SettingEffect string const ( EffectHot SettingEffect = "hot" // 立即生效 EffectNewRun SettingEffect = "new-run" // 仅影响新 run EffectRestart SettingEffect = "restart" // 需重启 ) // SettingDesc 描述一个设置项;设置页按此渲染并标注生效时机(schema 驱动)。 type SettingDesc struct { Key string `json:"key"` Group string `json:"group"` // 分区:models | profiles | tools | knowledge | ui | plugin: Label string `json:"label"` Description string `json:"description,omitempty"` Type SettingType `json:"type"` Default any `json:"default,omitempty"` Options []string `json:"options,omitempty"` // enum Effect SettingEffect `json:"effect"` Secret bool `json:"secret,omitempty"` } // EffectiveSettings 是覆盖链(system → user → project → conversation)深合并结果。 type EffectiveSettings map[string]any // MergeSettings 深合并:后者覆盖前者;map 递归合并,其它类型直接覆盖(4.9 数组显式覆盖)。 func MergeSettings(base, override map[string]any) map[string]any { out := make(map[string]any, len(base)+len(override)) for k, v := range base { out[k] = v } for k, v := range override { if bm, ok := base[k].(map[string]any); ok { if vm, ok2 := v.(map[string]any); ok2 { out[k] = MergeSettings(bm, vm) continue } } out[k] = v } return out } // GetString/GetBool/GetNumber 读取点路径("models.chat");缺省返回 def。 func (s EffectiveSettings) GetString(path, def string) string { v, ok := lookupPath(s, path) if !ok { return def } if str, ok2 := v.(string); ok2 { return str } return def } func (s EffectiveSettings) GetBool(path string, def bool) bool { v, ok := lookupPath(s, path) if !ok { return def } if b, ok2 := v.(bool); ok2 { return b } return def } func (s EffectiveSettings) GetNumber(path string, def float64) float64 { v, ok := lookupPath(s, path) if !ok { return def } if f, ok2 := v.(float64); ok2 { return f } return def } func lookupPath(m map[string]any, path string) (any, bool) { parts := splitPath(path) var cur any = m for _, p := range parts { cm, ok := cur.(map[string]any) if !ok { return nil, false } cur, ok = cm[p] if !ok { return nil, false } } return cur, true } func splitPath(path string) []string { var out []string cur := "" for i := 0; i < len(path); i++ { switch path[i] { case '.': out = append(out, cur) cur = "" default: cur += string(path[i]) } } return append(out, cur) } var _ = json.Marshal // 保持 encoding/json 引用(RawMessage 一致性)