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
1 change: 1 addition & 0 deletions contributing/samples/cli_coding_agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/__pycache__/
76 changes: 76 additions & 0 deletions contributing/samples/cli_coding_agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ADK CLI Coding Agent

An AI coding assistant built with Google ADK featuring file system operations, task planning, and colorful interactive CLI output.

**This is a toy example! It is not meant to be a replacement for fully featured products like the Gemini CLI or Claude Code.**


![alt text](image.png)

## Features


**File System Tools**
- `read_file` - Read file contents with metadata
- `write_file` - Create or overwrite files
- `update_file` - Replace text within files
- `list_directory` - List files/directories with glob patterns

**Task Planning**
- `create_plan` - Break down complex tasks into steps
- `update_plan` - Mark tasks as completed
- `get_plan` - View current plan and progress
- `reset_plan` - Clear completed plan

**Colorful Terminal UI**
- Interactive CLI with color-coded output
- Progress tracking with visual task lists
- Concise/verbose output modes

## Setup

1. **Navigate to this sample directory:**
```bash
cd contributing/samples/cli_coding_agent
```

2. **Install dependencies:**
```bash
uv pip install -r requirements.txt
```

3. **Authenticate with Google Cloud:**
```bash
gcloud auth application-default login
```

4. **Run the agent:**
```bash
uv run python -m agent
```

Or use ADK's built-in web interface:
```bash
adk web agent
```

## Usage

The agent automatically creates plans for multi-step tasks (3+ steps) and tracks progress:

```
[You]: Help me refactor this codebase

πŸ“‹ PLAN: Refactor Codebase
Progress: [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘] 2/3 (67%)
βœ“ [0] Analyze current structure
βœ“ [1] Extract common utilities
β—‹ [2] Update imports and tests

πŸ”§ update_file(file_path=utils.py, old_text=...)
βœ“ update_file
```

**Commands:**
- `exit/quit` - Exit the assistant
- `verbose` - Toggle verbose tool output
65 changes: 65 additions & 0 deletions contributing/samples/cli_coding_agent/agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Coding agent package for file system operations with ADK."""

import logging
from pathlib import Path
import sys

from dotenv import load_dotenv

# Load environment variables
load_dotenv()


def setup_logging(
level=logging.INFO, log_file='coding_agent.log', quiet_adk=True
):
"""Configure logging for the coding agent package.

Args:
level: Logging level (default: INFO)
log_file: Path to log file (default: 'coding_agent.log')
quiet_adk: If True, set ADK loggers to WARNING level (default: True)
"""
# Create formatters
detailed_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)

# Console handler (simple format)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(level)
console_handler.setFormatter(detailed_formatter)

# File handler (detailed format)
log_path = Path(log_file)
file_handler = logging.FileHandler(log_path)
file_handler.setLevel(logging.DEBUG) # Log everything to file
file_handler.setFormatter(detailed_formatter)

# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)

Comment on lines +41 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Configuring the root logger directly can be risky. If setup_logging is called multiple times (e.g., during tests or reloads), it will add duplicate handlers, leading to repeated log messages. It's safer to clear any existing handlers before adding new ones to make the function idempotent.

Suggested change
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)
# Configure root logger
root_logger = logging.getLogger()
root_logger.handlers.clear()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)

# Quiet down noisy libraries
if quiet_adk:
logging.getLogger('google_adk').setLevel(logging.WARNING)
logging.getLogger('google.genai').setLevel(logging.WARNING)
logging.getLogger('google_genai.types').setLevel(logging.ERROR)
logging.getLogger('httpx').setLevel(logging.WARNING)
logging.getLogger('httpcore').setLevel(logging.WARNING)
logging.getLogger('google_genai.models').setLevel(logging.WARNING)

return logging.getLogger(__name__)


# Initialize logging
logger = setup_logging()
logger.info('Coding agent package initialized')

# Import agent after logging is configured
from . import agent

__all__ = ['agent', 'logger', 'setup_logging']
Loading