Clover/main.py
Jarian Cottingham 392bcfa2ef feat: Implement AI agent with multi-turn conversation and tool calling
Major enhancements to Clover CLI:

 New Features:
- AI agent with multi-turn conversation capabilities
- Tool calling system with 11+ tools for file operations, Git, linting, etc.
- Step-by-step AI assistance with play-by-play commentary
- Enhanced interactive mode with better UX

🔧 Core Components Added:
- ai_agent.py: Main AI agent with conversation management
- models/: API client and model management system
- Comprehensive tool system for development tasks

🛠️ Tools Available:
- File operations (create, read, update, delete)
- Command execution with safety checks
- Git operations (status, diff, commit, push)
- Code linting and formatting
- Project structure analysis
- Security scanning and dependency management

💡 User Experience:
- Real-time tool execution summaries
- File creation with full path visibility
- Error handling and retry mechanisms
- Clean conversation flow until task completion

🧹 Repository Cleanup:
- Added comprehensive .gitignore
- Removed __pycache__ directories and build artifacts
- Organized project structure

The AI can now actually create files, run commands, and work through complex
development tasks step-by-step with full transparency.
2026-01-15 01:23:40 -06:00

179 lines
6.5 KiB
Python

#!/usr/bin/env python3
"""
Clover - A CLI tool for working with AI models to build and manage projects.
Interactive mode where you can run commands without prefixing 'clover'.
"""
import argparse
import os
import sys
# Add the current directory to Python path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from cli.commands import handle_command
from cli.parser import parse_args, print_help
def interactive_mode():
"""Run Clover in interactive mode"""
print("🍀 Clover Interactive AI Development Assistant")
print("=" * 60)
print("Welcome to Clover! An AI-powered development assistant that can:")
print(" • Create, edit, and manage files")
print(" • Execute commands and test code")
print(" • Work through problems step-by-step")
print(" • Use tools to solve complex development tasks")
print("")
print("🔧 Available Commands:")
print("- /init : Initialize project summary file")
print("- /list : List available AI models")
print("- /timeout SECS : Set timeout duration")
print("- /threads N : Set thread limit")
print("- /git_status : Check Git repository status")
print("- /lint_file FILE : Lint a specific file")
print("- /reset : Reset AI conversation history")
print("- /summary : Show AI conversation summary")
print("- /help : Show this help")
print("- /quit or /exit: Exit interactive mode")
print("")
print("💡 Just describe what you want to build and the AI will:")
print(" → Break down the task into steps")
print(" → Create and test files as needed")
print(" → Continue until the task is complete")
print("=" * 60)
print("🚀 Ready! Enter your development request below:")
while True:
try:
# Get user input
user_input = input("\n🍀 > ").strip()
# Handle exit commands
if user_input.lower() in ["/quit", "/exit", "exit", "quit"]:
print("\n👋 Thanks for using Clover! Goodbye!")
break
# Handle help command
if user_input.lower() == "/help":
print_help()
continue
# If input is empty, continue
if not user_input:
continue
# Parse and handle the command (prefix with clover for parsing)
# We'll create a fake args object for command handling in interactive mode
if user_input.startswith("/"):
# This is already a special command - no prefix needed
args = argparse.Namespace()
if user_input == "/init":
args.init = True
args.list = False
args.timeout = None
args.threads = None
args.prompt = None
elif user_input == "/list":
args.init = False
args.list = True
args.timeout = None
args.threads = None
args.prompt = None
elif user_input.startswith("/timeout "):
try:
seconds = int(user_input.split()[1])
args.init = False
args.list = False
args.timeout = seconds
args.threads = None
args.prompt = None
except (ValueError, IndexError):
print("Usage: /timeout <seconds>")
continue
elif user_input.startswith("/threads "):
try:
count = int(user_input.split()[1])
args.init = False
args.list = False
args.timeout = None
args.threads = count
args.prompt = None
except (ValueError, IndexError):
print("Usage: /threads <count>")
continue
elif user_input == "/git_status":
# For git commands we might need to handle differently
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = "/git_status"
elif user_input.startswith("/lint_file "):
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = user_input
elif user_input == "/reset":
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = "/reset"
elif user_input == "/summary":
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = "/summary"
else:
# Treat as regular command for now
args = argparse.Namespace()
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = user_input
try:
handle_command(args)
except Exception as e:
print(f"Error executing command: {e}")
else:
# Treat as regular query
args = argparse.Namespace()
args.init = False
args.list = False
args.timeout = None
args.threads = None
args.prompt = user_input
try:
handle_command(args)
except Exception as e:
print(f"Error executing command: {e}")
except KeyboardInterrupt:
print("\n\n🛑 Session interrupted. Thanks for using Clover!")
break
except EOFError:
print("\n👋 Thanks for using Clover! Goodbye!")
break
def main():
"""Main entry point"""
# Parse arguments
args = parse_args()
# Check if running in interactive mode (no arguments provided)
if len(sys.argv) == 1:
interactive_mode()
else:
# Run single command mode
handle_command(args)
if __name__ == "__main__":
main()