feat: Add AI-powered tool system with function calling capabilities#3
feat: Add AI-powered tool system with function calling capabilities#3themusicman merged 5 commits intomainfrom
Conversation
- add tools package with filesystem, git, shell, and agent tools - implement unified tool interface and execution system - add ollama and simple agent implementations for AI interactions - enhance ask command with tool integration - simplify init command implementation - update configuration with expanded tool capabilities - add required dependencies BREAKING CHANGE: restructured command interface and configuration format
…wered system commands
There was a problem hiding this comment.
Pull Request Overview
This PR introduces a comprehensive AI-powered tool system that enables intelligent interaction with system commands and operations through LangChain integration. The implementation adds function calling capabilities to the existing ask command and provides specialized tools for filesystem, git, shell, and commit message operations.
Key changes include:
- Complete tool ecosystem with unified interface for AI-powered operations
- Enhanced ask command with tool integration and function calling support
- AI agent implementations supporting both Ollama and simplified execution patterns
Reviewed Changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/tool.go | Core tool interface and registry system with JSON schema support |
| tools/simple_agent.go | Simplified agent implementation with direct query handling patterns |
| tools/ollama_agent.go | Full LangChain-integrated agent with conversation management |
| tools/shell_tool.go | Whitelisted shell command execution tool |
| tools/git_tool.go | Git operations tool with smart defaults |
| tools/filesystem_tool.go | File system operations tool with safety controls |
| tools/commit_message_tool.go | AI-powered commit message generation tool |
| cmd/ask.go | Enhanced ask command with tool calling capabilities |
| go.mod | Updated dependencies for LangChain integration |
| cmd/init.go | Updated configuration template with AI settings |
| .workie.yaml | Comprehensive configuration with AI and tool settings |
| toolDescriptions := "You are an AI assistant with access to tools that can execute system commands. You have access to the following tools:\n\n" | ||
|
|
||
| for _, tool := range tools { | ||
| params, _ := json.MarshalIndent(tool.Parameters(), "", " ") |
There was a problem hiding this comment.
Error from json.MarshalIndent is silently ignored. This could result in empty or incomplete parameter documentation being shown to users, making it difficult to understand how to use tools properly.
| params, _ := json.MarshalIndent(tool.Parameters(), "", " ") | |
| params, err := json.MarshalIndent(tool.Parameters(), "", " ") | |
| if err != nil { | |
| toolDescriptions += "Tool: " + tool.Name() + "\n" | |
| toolDescriptions += "Description: " + tool.Description() + "\n" | |
| toolDescriptions += "Parameters: [Error formatting parameters: " + err.Error() + "]\n\n" | |
| continue | |
| } |
| fmt.Println("Detected list files query, using shell tool directly") | ||
| } | ||
|
|
||
| tool, _ := s.registry.Get("shell") |
There was a problem hiding this comment.
Tool retrieval error is ignored. If the shell tool is not registered, this will cause a panic when calling tool.Execute. Should check the exists boolean and handle the error gracefully.
| tool, _ := s.registry.Get("shell") | |
| tool, exists := s.registry.Get("shell") | |
| if !exists { | |
| return "", fmt.Errorf("shell tool is not registered in the tool registry") | |
| } |
| fmt.Println("Detected branch query, using git tool directly") | ||
| } | ||
|
|
||
| tool, _ := s.registry.Get("git") |
There was a problem hiding this comment.
Tool retrieval error is ignored. If the git tool is not registered, this will cause a panic when calling tool.Execute. Should check the exists boolean and handle the error gracefully.
| tool, _ := s.registry.Get("git") | |
| tool, exists := s.registry.Get("git") | |
| if !exists { | |
| return "", fmt.Errorf("the 'git' tool is not registered in the tool registry") | |
| } |
| fmt.Println("Detected pwd query, using shell tool directly") | ||
| } | ||
|
|
||
| tool, _ := s.registry.Get("shell") |
There was a problem hiding this comment.
Tool retrieval error is ignored. If the shell tool is not registered, this will cause a panic when calling tool.Execute. Should check the exists boolean and handle the error gracefully.
| tool, _ := s.registry.Get("shell") | |
| tool, exists := s.registry.Get("shell") | |
| if !exists { | |
| return "", fmt.Errorf("shell tool is not registered in the tool registry") | |
| } |
|
|
||
| // generateCommitMessageWithGit uses git tools to analyze changes | ||
| func (s *SimpleAgent) generateCommitMessageWithGit(ctx context.Context) (string, error) { | ||
| gitTool, _ := s.registry.Get("git") |
There was a problem hiding this comment.
Tool retrieval error is ignored. If the git tool is not registered, this will cause a panic when calling tool.Execute. Should check the exists boolean and handle the error gracefully.
| gitTool, _ := s.registry.Get("git") | |
| gitTool, exists := s.registry.Get("git") | |
| if !exists { | |
| return "", fmt.Errorf("git tool is not registered in the tool registry") | |
| } |
|
|
||
| // Clean the path to prevent directory traversal | ||
| path = filepath.Clean(path) | ||
|
|
There was a problem hiding this comment.
The filepath.Clean() function alone is insufficient to prevent directory traversal attacks. An attacker could still access files outside the intended directory using paths like '../../../etc/passwd'. Consider implementing additional validation to restrict access to a specific base directory.
| // Clean the path to prevent directory traversal | |
| path = filepath.Clean(path) | |
| // Define the base directory for file operations | |
| baseDir := "/safe/base/directory" | |
| // Clean the path to prevent directory traversal | |
| path = filepath.Clean(path) | |
| // Ensure the path is within the base directory | |
| if !strings.HasPrefix(path, filepath.Clean(baseDir)+string(os.PathSeparator)) { | |
| return "", fmt.Errorf("access to the path is restricted: %s", path) | |
| } |
| commitType = "feat" | ||
| if len(added) == 1 { | ||
| fileName := getFileName(added[0]) | ||
| if fileName == "commit_message_tool.go" { |
There was a problem hiding this comment.
Hard-coded filename check creates brittle logic that will break if the file is renamed. This creates a maintenance burden and inconsistent behavior. Consider using more generic pattern matching or removing this special case.
| if fileName == "commit_message_tool.go" { | |
| if strings.Contains(fileName, "commit_message_tool") { |
- Add proper error handling for json.MarshalIndent in FormatToolsPrompt - Fix all tool registry lookups to check existence before use - Add directory traversal protection in FileSystemTool - Replace hard-coded filename check with pattern matching
Overview
This PR introduces a comprehensive tool system that enables AI-powered interactions with system commands and operations through LangChain integration.
✨ Key Features
🔧 Technical Changes
New Components
tools/package with complete tool ecosystemOllamaAgentandSimpleAgentimplementationsToolinterface for consistent tool executionEnhanced Commands
Configuration Updates
.workie.yamlwith comprehensive tool configuration📊 Stats
🚨 Breaking Changes
🧪 Usage Examples
Dependencies Added
Ready for review! 🚀