diff --git a/internal/bot/bot.go b/internal/bot/bot.go index 8b6a9aa..e31006a 100644 --- a/internal/bot/bot.go +++ b/internal/bot/bot.go @@ -118,6 +118,10 @@ func (b *Bot) CurrentRoles() (tool, vision string) { b.visionProvider.Name + "/" + b.visionModel } +func (b *Bot) Tools() []string { + return toolRegistry.List() +} + func (b *Bot) ContextDump() string { var sb strings.Builder sb.WriteString("[系统] " + b.systemPrompt + "\n") diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 35fc160..8744d81 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -29,6 +29,7 @@ func (h *Handler) Handle(input string) bool { fmt.Println(" /think 开启或关闭当前供应商的思考模式") fmt.Println(" /effort 设置思考强度") fmt.Println(" /context 打印当前聊天上下文") + fmt.Println(" /tools 列出可用工具") fmt.Println(" /info 显示当前供应商、模型和思考配置") fmt.Println(" /exit 退出") case "/models": @@ -69,6 +70,10 @@ func (h *Handler) Handle(input string) bool { fmt.Printf("思考强度已设置为 %s\n", args[0]) case "/context": fmt.Print(h.bot.ContextDump()) + case "/tools": + for _, t := range h.bot.Tools() { + fmt.Println(" " + t) + } case "/info": provider, model := h.bot.Current() thinking, effort := h.bot.ThinkingConfig() diff --git a/internal/cli/complete.go b/internal/cli/complete.go index b31d807..b04f7f4 100644 --- a/internal/cli/complete.go +++ b/internal/cli/complete.go @@ -2,7 +2,7 @@ package cli import "strings" -var commands = []string{"/exit", "/quit", "/help", "/models", "/use", "/think", "/effort", "/context", "/info"} +var commands = []string{"/exit", "/quit", "/help", "/models", "/use", "/think", "/effort", "/context", "/tools", "/info"} func Complete(line string, models []string) []string { fields := strings.Fields(line) diff --git a/internal/tools/tools.go b/internal/tools/tools.go index a48180c..a8de274 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -3,6 +3,7 @@ package tools import ( "encoding/json" "fmt" + "sort" "github.com/openai/openai-go" "github.com/openai/openai-go/packages/param" @@ -33,6 +34,19 @@ func (r *Registry) Get(name string) (Tool, bool) { return t, ok } +func (r *Registry) List() []string { + names := make([]string, 0, len(r.tools)) + for name := range r.tools { + names = append(names, name) + } + sort.Strings(names) + out := make([]string, 0, len(names)) + for _, name := range names { + out = append(out, fmt.Sprintf("%s - %s", name, r.tools[name].Description())) + } + return out +} + func (r *Registry) ParamList() []openai.ChatCompletionToolParam { out := make([]openai.ChatCompletionToolParam, 0, len(r.tools)) for _, t := range r.tools { diff --git a/internal/tools/tools_test.go b/internal/tools/tools_test.go index 906e584..63b2fb2 100644 --- a/internal/tools/tools_test.go +++ b/internal/tools/tools_test.go @@ -84,4 +84,14 @@ func TestRegistry(t *testing.T) { if _, err := r.Execute("nonexistent", nil); err == nil { t.Error("执行未知工具应返回错误") } + list := r.List() + if len(list) != 3 { + t.Fatalf("List 数量 = %d, want 3", len(list)) + } + wantOrder := []string{"calculate", "get_current_time", "random_number"} + for i, want := range wantOrder { + if !strings.HasPrefix(list[i], want+" - ") { + t.Errorf("List[%d] = %q, want 前缀 %q", i, list[i], want+" - ") + } + } }