Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions mini_agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import json
from pathlib import Path
from time import perf_counter

import tiktoken

Expand Down Expand Up @@ -285,8 +286,10 @@ async def run(self) -> str:
print(f"{Colors.DIM}📝 Log file: {self.logger.get_log_file_path()}{Colors.RESET}")

step = 0
step_start_time = None

while step < self.max_steps:
step_start_time = perf_counter()
# Check and summarize message history to prevent context overflow
await self._summarize_messages()

Expand Down Expand Up @@ -353,6 +356,8 @@ async def run(self) -> str:

# Check if task is complete (no tool calls)
if not response.tool_calls:
step_elapsed = perf_counter() - step_start_time
print(f"{Colors.DIM}⏱️ Step {step + 1} completed in {step_elapsed:.2f}s{Colors.RESET}")
return response.content

# Execute tool calls
Expand Down Expand Up @@ -428,6 +433,9 @@ async def run(self) -> str:
)
self.messages.append(tool_msg)

step_elapsed = perf_counter() - step_start_time
print(f"{Colors.DIM}⏱️ Step {step + 1} completed in {step_elapsed:.2f}s{Colors.RESET}")

step += 1

# Max steps reached
Expand Down
100 changes: 99 additions & 1 deletion mini_agent/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import argparse
import asyncio
import platform
import subprocess
from datetime import datetime
from pathlib import Path
from typing import List
Expand Down Expand Up @@ -173,6 +175,8 @@ def print_stats(agent: Agent, session_start: datetime):
print(f" - Assistant Replies: {Colors.BRIGHT_BLUE}{assistant_msgs}{Colors.RESET}")
print(f" - Tool Calls: {Colors.BRIGHT_YELLOW}{tool_msgs}{Colors.RESET}")
print(f" Available Tools: {len(agent.tools)}")
if hasattr(agent, 'api_total_tokens') and agent.api_total_tokens > 0:
print(f" API Tokens Used: {Colors.BRIGHT_MAGENTA}{agent.api_total_tokens:,}{Colors.RESET}")
print(f"{Colors.DIM}{'─' * 40}{Colors.RESET}\n")


Expand Down Expand Up @@ -205,6 +209,10 @@ def parse_args() -> argparse.Namespace:
version="mini-agent 0.1.0",
)

subparsers = parser.add_subparsers(dest="command", help="Available commands")

log_parser = subparsers.add_parser("log", help="Show log directory and open file manager")

return parser.parse_args()


Expand Down Expand Up @@ -451,7 +459,7 @@ def on_retry(exception: Exception, attempt: int):
# 9. Setup prompt_toolkit session
# Command completer
command_completer = WordCompleter(
["/help", "/clear", "/history", "/stats", "/exit", "/quit", "/q"],
["/help", "/clear", "/history", "/stats", "/log", "/exit", "/quit", "/q"],
ignore_case=True,
sentence=True,
)
Expand Down Expand Up @@ -540,6 +548,63 @@ def _(event):
print_stats(agent, session_start)
continue

elif command.startswith("/log"):
log_dir = Path.home() / ".mini-agent" / "log"

if command == "/log":
print(f"\n{Colors.BRIGHT_CYAN}📁 Log Directory: {log_dir}{Colors.RESET}")
if log_dir.exists() and log_dir.is_dir():
log_files = list(log_dir.glob("*.log"))
if log_files:
log_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}")
print(f"{Colors.BOLD}{Colors.BRIGHT_YELLOW}Available Log Files:{Colors.RESET}")
for i, log_file in enumerate(log_files[:10], 1):
mtime = datetime.fromtimestamp(log_file.stat().st_mtime)
size = log_file.stat().st_size
print(f" {Colors.GREEN}{i:2d}.{Colors.RESET} {Colors.BRIGHT_WHITE}{log_file.name}{Colors.RESET}")
print(f" {Colors.DIM}Modified: {mtime.strftime('%Y-%m-%d %H:%M:%S')}, Size: {size:,} bytes{Colors.RESET}")
if len(log_files) > 10:
print(f" {Colors.DIM}... and {len(log_files) - 10} more files{Colors.RESET}")
print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}")
if platform.system() == "Darwin":
subprocess.run(["open", str(log_dir)])
elif platform.system() == "Windows":
subprocess.run(["explorer", str(log_dir)])
elif platform.system() == "Linux":
try:
subprocess.run(["xdg-open", str(log_dir)])
except FileNotFoundError:
print(f"{Colors.YELLOW}Could not open file manager. Please install xdg-utils or navigate manually.{Colors.RESET}")
else:
print(f"{Colors.YELLOW}No log files found in directory.{Colors.RESET}")
else:
print(f"{Colors.RED}Log directory does not exist: {log_dir}{Colors.RESET}")
print()
continue

parts = command.split(maxsplit=1)
if len(parts) == 2:
pattern = parts[1].strip('"\'')
if pattern:
log_file = log_dir / pattern
if log_file.exists() and log_file.is_file():
print(f"\n{Colors.BRIGHT_CYAN}📄 Reading: {log_file}{Colors.RESET}")
print(f"{Colors.DIM}{'─' * 80}{Colors.RESET}")
try:
with open(log_file, 'r', encoding='utf-8') as f:
content = f.read()
print(content)
print(f"{Colors.DIM}{'─' * 80}{Colors.RESET}")
print(f"\n{Colors.GREEN}✅ End of file{Colors.RESET}\n")
except Exception as e:
print(f"\n{Colors.RED}❌ Error reading file: {e}{Colors.RESET}\n")
else:
print(f"\n{Colors.RED}❌ Log file not found: {log_file}{Colors.RESET}\n")
else:
print(f"\n{Colors.YELLOW}Usage: /log \"filename.log\" or /log \"*.log\" pattern{Colors.RESET}\n")
continue

else:
print(f"{Colors.RED}❌ Unknown command: {user_input}{Colors.RESET}")
print(f"{Colors.DIM}Type /help to see available commands{Colors.RESET}\n")
Expand Down Expand Up @@ -582,6 +647,39 @@ def main():
# Parse command line arguments
args = parse_args()

# Handle log command
if args.command == "log":
log_dir = Path.home() / ".mini-agent" / "log"
print(f"{Colors.BRIGHT_CYAN}📁 Log Directory: {log_dir}{Colors.RESET}")
if log_dir.exists() and log_dir.is_dir():
log_files = list(log_dir.glob("*.log"))
if log_files:
log_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}")
print(f"{Colors.BOLD}{Colors.BRIGHT_YELLOW}Available Log Files:{Colors.RESET}")
for i, log_file in enumerate(log_files[:10], 1):
mtime = datetime.fromtimestamp(log_file.stat().st_mtime)
size = log_file.stat().st_size
print(f" {Colors.GREEN}{i:2d}.{Colors.RESET} {Colors.BRIGHT_WHITE}{log_file.name}{Colors.RESET}")
print(f" {Colors.DIM}Modified: {mtime.strftime('%Y-%m-%d %H:%M:%S')}, Size: {size:,} bytes{Colors.RESET}")
if len(log_files) > 10:
print(f" {Colors.DIM}... and {len(log_files) - 10} more files{Colors.RESET}")
print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}")
if platform.system() == "Darwin":
subprocess.run(["open", str(log_dir)])
elif platform.system() == "Windows":
subprocess.run(["explorer", str(log_dir)])
elif platform.system() == "Linux":
try:
subprocess.run(["xdg-open", str(log_dir)])
except FileNotFoundError:
print(f"{Colors.YELLOW}Could not open file manager. Please install xdg-utils or navigate manually.{Colors.RESET}")
else:
print(f"{Colors.YELLOW}No log files found in directory.{Colors.RESET}")
else:
print(f"{Colors.RED}Log directory does not exist: {log_dir}{Colors.RESET}")
return

# Determine workspace directory
if args.workspace:
workspace_dir = Path(args.workspace).absolute()
Expand Down