Skip to content

Commit

Permalink
Update terminal command and ai_cli script with improvements for input…
Browse files Browse the repository at this point in the history
…, output, error handling, debugging, and AI service configuration.
  • Loading branch information
MikeBirdTech committed Nov 14, 2024
1 parent b552113 commit 16565e9
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This toolkit provides two main command interfaces:
Generate and execute terminal commands from natural language.

```bash
ai do Your command description here
ai do <your optional command description>
```

### 2. Calendar Manager (`ai cal`)
Expand Down
81 changes: 62 additions & 19 deletions src/tool_use/scripts/ai_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import time
from typing import Dict, Optional
from pynput.keyboard import Controller
from rich.console import Console
from ..utils.ai_service import AIService
from ..config_manager import config_manager

console = Console()
keyboard = Controller()


Expand Down Expand Up @@ -40,16 +42,13 @@ def query_ai_service(
try:
return ai_service.query(prompt).strip()
except Exception as e:
print(f"Error querying AI service: {e}", file=sys.stderr)
console.print(f"[red]Error querying AI service: {e}[/red]", file=sys.stderr)
sys.exit(1)


def write_to_terminal(command: str) -> None:
# Clear the current line
sys.stdout.write("\r" + " " * (len(command) + 1) + "\r")
sys.stdout.flush()

# Small delay to ensure terminal is ready
time.sleep(0.1)
keyboard.type(command)

Expand All @@ -59,23 +58,40 @@ def execute_command(command: str) -> None:
result = subprocess.run(
command, shell=True, check=True, text=True, capture_output=True
)
print(f"\nCommand output:\n{result.stdout}")
if result.stdout:
console.print("\nCommand output:", style="green")
console.print(result.stdout)
if result.stderr:
print(f"Error output:\n{result.stderr}")
console.print("\nWarning output:", style="yellow")
console.print(result.stderr)
except subprocess.CalledProcessError as e:
print(f"Command failed with return code: {e.returncode}", file=sys.stderr)
console.print(f"\n[red]Command failed with return code: {e.returncode}[/red]")
if e.stdout:
print(f"Command output:\n{e.stdout}")
console.print("\nCommand output:")
console.print(e.stdout)
if e.stderr:
print(f"Error output:\n{e.stderr}")
console.print("\n[red]Error output:[/red]")
console.print(e.stderr)


def get_command_explanation(command: str, service: str, model: Optional[str]) -> str:
"""Get an explanation of what the command does."""
ai_service = AIService(service, model)
prompt = f"""Explain what this shell command does in detail: {command}
Break down each part and flag. Be concise but thorough."""

try:
return ai_service.query(prompt).strip()
except Exception as e:
return f"Could not get explanation: {e}"


def get_user_query() -> str:
"""Prompt the user for their natural language query."""
print("\nPlease enter your command request (what would you like to do?):")
console.print("\nWhat command would you like me to generate?")
query = input("> ").strip()
while not query:
print("Query cannot be empty. Please try again:")
console.print("[yellow]Query cannot be empty. Please try again:[/yellow]")
query = input("> ").strip()
return query

Expand All @@ -88,18 +104,38 @@ def main(args=None):
help="Override default AI service",
)
parser.add_argument("--model", help="Override default AI model")
parser.add_argument(
"--debug", action="store_true", help="Show additional debug information"
)

# Parse known args first to separate flags from the input text
known_args, unknown_args = parser.parse_known_args(args)

# Get tool config
tool_config = config_manager.get_tool_config("do")
try:
tool_config = config_manager.get_tool_config("do")
except Exception as e:
console.print(f"[red]Error loading config: {e}[/red]")
console.print("[yellow]Using default configuration[/yellow]")
tool_config = {
"ai_service": "anthropic",
"ai_model": None,
"write_to_terminal": True,
}

# Command-line args override config
service = known_args.service or tool_config["ai_service"]
model = known_args.model or tool_config["ai_model"]
model = known_args.model or tool_config.get("ai_model")
write_to_terminal_mode = tool_config.get("write_to_terminal", True)

# Debug output if requested
if known_args.debug:
console.print("\nDebug Information:", style="blue")
console.print(f"Service: {service}")
console.print(f"Model: {model}")
console.print(f"Write to terminal: {write_to_terminal_mode}")
console.print(f"Environment: {get_environment_info()}")

# Get the task description from arguments or prompt
input_text = " ".join(unknown_args) if unknown_args else ""
if not input_text:
Expand All @@ -110,7 +146,7 @@ def main(args=None):
command = query_ai_service(input_text, service, model, env_info)

# Show the command preview
print(f"\n\033[92m{command}\033[0m")
console.print(f"\n[green]{command}[/green]")

while True:
if write_to_terminal_mode:
Expand All @@ -123,14 +159,14 @@ def main(args=None):
choice = input(prompt).lower()

if choice == "e":
print("\nExplanation:")
explanation = get_command_explanation(command, service, model)
print(explanation)
print() # Extra newline for readability
console.print("\n[blue]Explanation:[/blue]")
console.print(explanation)
console.print() # Extra newline for readability
continue

if choice == "n":
print("Operation cancelled.")
console.print("[yellow]Operation cancelled.[/yellow]")
break

if choice == "":
Expand All @@ -142,4 +178,11 @@ def main(args=None):


if __name__ == "__main__":
main()
try:
main()
except KeyboardInterrupt:
console.print("\n[yellow]Operation cancelled by user.[/yellow]")
sys.exit(0)
except Exception as e:
console.print(f"\n[red]An unexpected error occurred: {e}[/red]")
sys.exit(1)

0 comments on commit 16565e9

Please sign in to comment.