package builtin import ( "context" "encoding/json" "fmt" "strings" "nub/internal/skill" "nub/internal/tool" ) // ReadSkillTool lädt den Body eines im Index (nur Name+Description) // angekündigten Skills nach (5.5, Progressive Disclosure). type ReadSkillTool struct { skills []skill.Skill } func NewReadSkillTool(skills []skill.Skill) *ReadSkillTool { return &ReadSkillTool{skills: skills} } func (*ReadSkillTool) Name() string { return "read_skill" } func (*ReadSkillTool) Description() string { return "Lädt den vollständigen Inhalt eines Skills nach Name." } func (*ReadSkillTool) Schema() json.RawMessage { return json.RawMessage(`{ "type": "object", "properties": { "name": {"type": "string"} }, "required": ["name"] }`) } type readSkillInput struct { Name string `json:"name"` } func (t *ReadSkillTool) Run(ctx context.Context, input json.RawMessage, env tool.Env) (tool.Result, error) { var in readSkillInput if err := json.Unmarshal(input, &in); err != nil { return tool.Result{ForModel: "invalid input: " + err.Error(), IsError: true}, nil } for _, s := range t.skills { if s.Name == in.Name { return tool.Result{ForModel: s.Body, ForUI: SkillResult{Name: s.Name, Dir: s.Dir}}, nil } } names := make([]string, len(t.skills)) for i, s := range t.skills { names[i] = s.Name } return tool.Result{ ForModel: fmt.Sprintf("unknown skill %q. Available: %s", in.Name, strings.Join(names, ", ")), IsError: true, }, nil } type SkillResult struct { Name string Dir string }