getToolContextString centraliza a geração do contexto de ferramentas.
()
| 1217 | |
| 1218 | // getToolContextString centraliza a geração do contexto de ferramentas. |
| 1219 | func (a *AgentMode) getToolContextString() string { |
| 1220 | if a.cli.pluginManager == nil { |
| 1221 | return "" |
| 1222 | } |
| 1223 | |
| 1224 | // Sync MCP shadow state: hide built-ins overridden by connected MCP servers, |
| 1225 | // restore them automatically when servers disconnect. |
| 1226 | if a.cli.mcpManager != nil { |
| 1227 | a.cli.pluginManager.SetShadowedBuiltins(a.cli.mcpManager.GetShadowedBuiltins()) |
| 1228 | } else { |
| 1229 | a.cli.pluginManager.SetShadowedBuiltins(nil) |
| 1230 | } |
| 1231 | |
| 1232 | plugins := a.cli.pluginManager.GetPlugins() |
| 1233 | if len(plugins) == 0 { |
| 1234 | return "" |
| 1235 | } |
| 1236 | |
| 1237 | // Deferred catalog (default): only the CORE work-loop tools carry their |
| 1238 | // full definition inline; every other builtin becomes a one-line index |
| 1239 | // entry the model expands on demand via @tools describe. Measured saving: |
| 1240 | // ~11k → ~2.5k tokens of tool definitions per agent turn. External |
| 1241 | // (user-installed) plugins stay fully rendered — few and explicitly |
| 1242 | // chosen. CHATCLI_AGENT_TOOL_CATALOG=full restores the legacy behavior. |
| 1243 | deferred := toolCatalogDeferred() |
| 1244 | toolDescriptions := make([]string, 0, len(plugins)) |
| 1245 | indexLines := make([]string, 0, len(plugins)) |
| 1246 | coderCheatSheet := "" |
| 1247 | for _, plugin := range plugins { |
| 1248 | if deferred && plugin.Path() == "" && !isCoreTool(plugin.Name()) { |
| 1249 | indexLines = append(indexLines, renderToolIndexLine(plugin)) |
| 1250 | continue |
| 1251 | } |
| 1252 | toolDescriptions = append(toolDescriptions, renderToolBlock(plugin, a.isCoderMode)) |
| 1253 | } |
| 1254 | |
| 1255 | if a.isCoderMode { |
| 1256 | coderCheatSheet = "Cheat sheet (@coder):\n" + |
| 1257 | "- read: {\"cmd\":\"read\",\"args\":{\"file\":\"main.go\"}}\n" + |
| 1258 | "- search: {\"cmd\":\"search\",\"args\":{\"term\":\"Login\",\"dir\":\".\"}}\n" + |
| 1259 | "- write: {\"cmd\":\"write\",\"args\":{\"file\":\"x.go\",\"encoding\":\"base64\",\"content\":\"...\"}}\n" + |
| 1260 | "- exec: {\"cmd\":\"exec\",\"args\":{\"cmd\":\"mkdir -p testeapi\"}}\n\n" |
| 1261 | } |
| 1262 | |
| 1263 | // Include MCP tools from connected servers (deferred schemas — only name+description) |
| 1264 | // Full parameter schemas are fetched on-demand when the tool is invoked. |
| 1265 | if a.cli.mcpManager != nil { |
| 1266 | mcpTools := a.cli.mcpManager.GetToolsSummary() |
| 1267 | if len(mcpTools) > 0 { |
| 1268 | toolDescriptions = append(toolDescriptions, buildMCPToolsSection(mcpTools, a.isCoderMode)) |
| 1269 | } else { |
| 1270 | // MCP is configured but no tools are usable right now: either a |
| 1271 | // background launch is still in progress or every server failed |
| 1272 | // to start. Tell the model explicitly so it does not fabricate |
| 1273 | // `mcp_*` calls and instead falls back to the listed tools. |
| 1274 | statuses := a.cli.mcpManager.GetServerStatus() |
| 1275 | if note := buildMCPEmptyNote(statuses); note != "" { |
| 1276 | toolDescriptions = append(toolDescriptions, note) |
no test coverage detected