Classify a tool call into a [`NodeKind`] based on tool name and arguments. This is the primary entry point for the rule-based classifier. It inspects the tool name first, then falls back to argument inspection for ambiguous tools (like `bash`). # Arguments `tool_name` — The tool name as reported by the agent (e.g., "read", "edit", "bash"). `tool_input` — The tool's input arguments as a JSON val
(
tool_name: &str,
tool_input: Option<&serde_json::Value>,
tool_output: Option<&str>,
status: Option<&str>,
)
| 78 | /// The [`NodeKind`] that best describes this tool call's role in the |
| 79 | /// agent's decision chain. |
| 80 | pub fn classify_tool_call( |
| 81 | tool_name: &str, |
| 82 | tool_input: Option<&serde_json::Value>, |
| 83 | tool_output: Option<&str>, |
| 84 | status: Option<&str>, |
| 85 | ) -> NodeKind { |
| 86 | // Error status always produces an error node, regardless of tool |
| 87 | if status == Some("error") { |
| 88 | return NodeKind::Error; |
| 89 | } |
| 90 | |
| 91 | let normalized = tool_name.to_lowercase(); |
| 92 | let normalized = normalized.trim(); |
| 93 | |
| 94 | match normalized { |
| 95 | // Read-family tools → Exploration |
| 96 | "read" | "read_file" | "readfile" | "view" | "cat" => NodeKind::Exploration, |
| 97 | |
| 98 | // Search tools → Exploration |
| 99 | "grep" | "glob" | "find_path" | "find" | "search" | "ripgrep" | "rg" => { |
| 100 | NodeKind::Exploration |
| 101 | } |
| 102 | |
| 103 | // Directory listing → Exploration |
| 104 | "list_directory" | "listdir" | "ls" | "list" | "tree" => NodeKind::Exploration, |
| 105 | |
| 106 | // Internal reasoning → Exploration |
| 107 | "thinking" | "think" | "reason" | "plan" => NodeKind::Exploration, |
| 108 | |
| 109 | // Fetch/web tools → Exploration |
| 110 | "fetch" | "curl" | "web_search" | "browser" => NodeKind::Exploration, |
| 111 | |
| 112 | // Write-family tools → Commitment |
| 113 | "edit" | "edit_file" | "editfile" => NodeKind::Commitment, |
| 114 | "write" | "write_file" | "writefile" | "write_to_file" => NodeKind::Commitment, |
| 115 | "multiedit" | "multi_edit" | "multifile_edit" => NodeKind::Commitment, |
| 116 | "patch" | "apply_patch" | "apply_diff" => NodeKind::Commitment, |
| 117 | "create" | "create_file" | "createfile" => NodeKind::Commitment, |
| 118 | "insert" | "replace" | "delete_file" | "remove_file" => NodeKind::Commitment, |
| 119 | |
| 120 | // Todo/note tools → Commitment (they write structured data) |
| 121 | "todocreate" | "todowrite" | "todo_create" | "todo_write" => NodeKind::Commitment, |
| 122 | |
| 123 | // Shell commands: inspect the command string to sub-classify |
| 124 | "bash" | "terminal" | "shell" | "command" | "exec" | "run" => { |
| 125 | classify_shell_command(tool_input, tool_output) |
| 126 | } |
| 127 | |
| 128 | // Task/sub-agent → Execution |
| 129 | "task" | "subagent" | "agent" | "dispatch" | "delegate" => NodeKind::Execution, |
| 130 | |
| 131 | // File operations that are ambiguous — classify by looking at args |
| 132 | "mv" | "move" | "rename" | "move_path" | "copy" | "copy_path" => NodeKind::Commitment, |
| 133 | |
| 134 | // Diagnostic tools → Exploration |
| 135 | "diagnostics" | "diagnostic" | "check" => NodeKind::Exploration, |
| 136 | |
| 137 | // Open tools (open file in editor/browser) → Exploration |
no test coverage detected