2026-04-13 20:43:37 +08:00
|
|
|
package runtime
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"cs-agent/internal/ai/runtime/registry"
|
|
|
|
|
"cs-agent/internal/ai/runtime/tools"
|
|
|
|
|
"cs-agent/internal/models"
|
|
|
|
|
"cs-agent/internal/pkg/toolx"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type toolCatalog struct {
|
|
|
|
|
registry *registry.Registry
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newToolCatalog() *toolCatalog {
|
|
|
|
|
return &toolCatalog{
|
2026-04-14 09:39:56 +08:00
|
|
|
registry: registry.NewRegistry(buildRuntimeStaticTools()...),
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-14 09:39:56 +08:00
|
|
|
func buildRuntimeStaticTools() []registry.Tool {
|
2026-04-14 09:56:52 +08:00
|
|
|
ret := make([]registry.Tool, 0, len(toolx.ListRuntimeStaticToolSpecs()))
|
2026-04-14 09:39:56 +08:00
|
|
|
for _, spec := range toolx.ListRuntimeStaticToolSpecs() {
|
2026-04-14 09:56:52 +08:00
|
|
|
tool := tools.NewRuntimeStaticTool(spec.Code)
|
|
|
|
|
if tool == nil {
|
2026-04-14 09:39:56 +08:00
|
|
|
continue
|
|
|
|
|
}
|
2026-04-14 09:56:52 +08:00
|
|
|
ret = append(ret, tool)
|
2026-04-14 09:39:56 +08:00
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 20:43:37 +08:00
|
|
|
func (c *toolCatalog) resolveForRun(req *Request) (*registry.ToolSet, error) {
|
|
|
|
|
if req == nil || req.ToolSet != nil || c == nil || c.registry == nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
return c.registry.Resolve(registry.Context{
|
|
|
|
|
Conversation: req.Conversation,
|
|
|
|
|
AIAgent: req.AIAgent,
|
|
|
|
|
AIConfig: req.AIConfig,
|
|
|
|
|
UserMessage: req.UserMessage,
|
|
|
|
|
AllowedToolCodes: c.resolveAllowedToolCodes(req.AIAgent, req.SelectedSkill),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *toolCatalog) resolveForResume(req *ResumeRequest) (*registry.ToolSet, error) {
|
|
|
|
|
if req == nil || req.ToolSet != nil || c == nil || c.registry == nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
return c.registry.Resolve(registry.Context{
|
|
|
|
|
Conversation: req.Conversation,
|
|
|
|
|
AIAgent: req.AIAgent,
|
|
|
|
|
AIConfig: req.AIConfig,
|
|
|
|
|
AllowedToolCodes: c.parseAgentAllowedToolCodes(req.AIAgent),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *toolCatalog) parseSkillAllowedToolCodes(skill *models.SkillDefinition) []string {
|
|
|
|
|
if skill == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
raw := strings.TrimSpace(skill.ToolWhitelist)
|
|
|
|
|
if raw == "" {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var items []string
|
|
|
|
|
if err := json.Unmarshal([]byte(raw), &items); err != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2026-04-14 09:39:56 +08:00
|
|
|
return toolx.NormalizeToolCodes(items)
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-17 17:57:01 +08:00
|
|
|
func (c *toolCatalog) parseAgentAllowedToolCodes(aiAgent models.AIAgent) []string {
|
2026-04-14 15:10:50 +08:00
|
|
|
ret := make([]string, 0)
|
|
|
|
|
if raw := strings.TrimSpace(aiAgent.AllowedMCPTools); raw != "" {
|
|
|
|
|
items, err := toolx.ParseAgentMCPToolsJSON(raw)
|
|
|
|
|
if err == nil {
|
|
|
|
|
for _, item := range items {
|
|
|
|
|
ret = append(ret, item.ToolCode)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|
2026-04-14 15:10:50 +08:00
|
|
|
if raw := strings.TrimSpace(aiAgent.AllowedGraphTools); raw != "" {
|
|
|
|
|
var graphTools []string
|
|
|
|
|
if err := json.Unmarshal([]byte(raw), &graphTools); err == nil {
|
|
|
|
|
ret = append(ret, graphTools...)
|
|
|
|
|
}
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|
2026-04-14 09:39:56 +08:00
|
|
|
return toolx.NormalizeToolCodes(ret)
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-17 17:57:01 +08:00
|
|
|
func (c *toolCatalog) resolveAllowedToolCodes(aiAgent models.AIAgent, skill *models.SkillDefinition) []string {
|
2026-04-14 09:39:56 +08:00
|
|
|
return toolx.IntersectToolCodes(c.parseAgentAllowedToolCodes(aiAgent), c.parseSkillAllowedToolCodes(skill))
|
2026-04-13 20:43:37 +08:00
|
|
|
}
|