FirstToolCallExample 根据 tools 列表的语义,生成一个具体的"先做这个"示例, 帮模型跳出 sandbox 思维。优先级:bash/shell → glob → list_files → read → 任意。 workingDir 用于替换占位符;若为空用 "."。
(tools []official.Tool, workingDir string)
| 117 | // 帮模型跳出 sandbox 思维。优先级:bash/shell → glob → list_files → read → 任意。 |
| 118 | // workingDir 用于替换占位符;若为空用 "."。 |
| 119 | func FirstToolCallExample(tools []official.Tool, workingDir string) string { |
| 120 | if len(tools) == 0 { |
| 121 | return "" |
| 122 | } |
| 123 | wd := strings.ReplaceAll(workingDir, `\`, `\\`) |
| 124 | if wd == "" { |
| 125 | wd = "." |
| 126 | } |
| 127 | names := make([]string, 0, len(tools)) |
| 128 | for _, t := range tools { |
| 129 | if t.Type == "function" { |
| 130 | names = append(names, t.Function.Name) |
| 131 | } |
| 132 | } |
| 133 | if len(names) == 0 { |
| 134 | return "" |
| 135 | } |
| 136 | if n := pickFirst(names, ShellToolNames); n != "" { |
| 137 | return fmt.Sprintf(`<tool_call>{"name": %q, "arguments": {"command": "Get-ChildItem -Force"}}</tool_call>`, n) |
| 138 | } |
| 139 | if n := pickFirst(names, []string{"glob", "find", "search_files", "file_search"}); n != "" { |
| 140 | return fmt.Sprintf(`<tool_call>{"name": %q, "arguments": {"pattern": "*"}}</tool_call>`, n) |
| 141 | } |
| 142 | if n := pickFirst(names, []string{"list", "ls", "read_directory", "list_files", "list_directory"}); n != "" { |
| 143 | return fmt.Sprintf(`<tool_call>{"name": %q, "arguments": {"path": %q}}</tool_call>`, n, wd) |
| 144 | } |
| 145 | if n := pickFirst(names, []string{"read", "read_file", "cat", "open", "view"}); n != "" { |
| 146 | return fmt.Sprintf(`<tool_call>{"name": %q, "arguments": {"filePath": %q}}</tool_call>`, n, wd) |
| 147 | } |
| 148 | return fmt.Sprintf(`<tool_call>{"name": %q, "arguments": {}}</tool_call>`, names[0]) |
| 149 | } |
| 150 | |
| 151 | func pickFirst(haystack []string, candidates []string) string { |
| 152 | for _, h := range haystack { |