-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Add CLI coding agent sample #4253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
A toy AI coding assistant demonstrating ADK tool usage with: - File system tools (read, write, update, list directory) - Task planning tools (create, update, get, reset plan) - Colorful interactive CLI with progress tracking - Verbose/concise output modes This sample shows how to build an interactive CLI agent with custom tools for file manipulation and task management.
Summary of ChangesHello @LiamConnell, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request adds a comprehensive new sample application to the repository: a command-line interface (CLI) coding assistant. The primary goal is to illustrate how to leverage the ADK framework to build an interactive agent that can perform practical development tasks. It focuses on providing a clear, educational example of integrating custom functionalities like file system manipulation and structured task planning within an ADK-powered agent, complete with an engaging terminal user interface. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Response from ADK Triaging Agent Hello @LiamConnell, thank you for creating this PR! Could you please associate the github issue with this PR? If there is no existing issue, could you please create one? This information will help reviewers to review your PR more efficiently. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces an excellent and comprehensive sample of a CLI coding assistant using the ADK. The interactive CLI with its colorful output and progress tracking is a great touch. The code is generally well-structured and demonstrates several important ADK patterns. I've identified one critical issue: a missing dependency in requirements.txt that will prevent the sample from running. Additionally, I've provided some feedback to improve code robustness, maintainability, and to highlight best practices for state management, which is particularly important for an educational example like this one. Overall, this is a valuable addition to the samples.
| google-adk | ||
| google-genai |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| from typing import Optional | ||
|
|
||
| # Global plan state | ||
| _current_plan: dict | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a global variable _current_plan to manage state is simple for this toy example, but it's important to be aware of its limitations. This approach is not thread-safe and would not work correctly in a multi-user or multi-session environment, as all concurrent executions would share and potentially overwrite the same plan. For a more robust solution, especially in a real application, this state should be managed on a per-session basis. The ADK provides session.state for this purpose, which would be the idiomatic way to handle session-specific data.
| root_logger = logging.getLogger() | ||
| root_logger.setLevel(logging.DEBUG) | ||
| root_logger.addHandler(console_handler) | ||
| root_logger.addHandler(file_handler) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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) |
| if isinstance(response, dict): | ||
| print(f"{Colors.GRAY} Result:{Colors.RESET}") | ||
| formatted_response = json.dumps(response, indent=4) | ||
| for line in formatted_response.split("\n"): | ||
| print(f" {line}") | ||
| elif isinstance(response, list): | ||
| print(f"{Colors.GRAY} Result:{Colors.RESET}") | ||
| formatted_response = json.dumps(response, indent=4) | ||
| for line in formatted_response.split("\n"): | ||
| print(f" {line}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code for handling dict and list responses is duplicated. You can combine these two blocks to make the code more concise and maintainable by following the Don't Repeat Yourself (DRY) principle.
| if isinstance(response, dict): | |
| print(f"{Colors.GRAY} Result:{Colors.RESET}") | |
| formatted_response = json.dumps(response, indent=4) | |
| for line in formatted_response.split("\n"): | |
| print(f" {line}") | |
| elif isinstance(response, list): | |
| print(f"{Colors.GRAY} Result:{Colors.RESET}") | |
| formatted_response = json.dumps(response, indent=4) | |
| for line in formatted_response.split("\n"): | |
| print(f" {line}") | |
| if isinstance(response, (dict, list)): | |
| print(f"{Colors.GRAY} Result:{Colors.RESET}") | |
| formatted_response = json.dumps(response, indent=4) | |
| for line in formatted_response.split("\n"): | |
| print(f" {line}") |
| 2. Work through tasks sequentially | ||
| 3. Mark each task complete as you finish it | ||
| 4. The plan will be displayed visually with progress tracking | ||
| 5. When you finish all the tasks, reset the plan. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "lines": None, | ||
| "is_binary": True, | ||
| } | ||
| except PermissionError as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
This PR adds a new sample demonstrating a CLI coding assistant built with ADK. It's a simple, educational example showing how to build an interactive terminal agent with custom tools.
Note: This is intentionally a toy example to demonstrate ADK patterns, not a production-ready coding assistant.
Features
File System Tools
read_file- Read file contents with metadatawrite_file- Create or overwrite filesupdate_file- Replace text within fileslist_directory- List files/directories with glob patternsTask Planning Tools
create_plan- Break down complex tasks into stepsupdate_plan- Mark tasks as completedget_plan- View current plan and progressreset_plan- Clear completed planInteractive CLI
adk webfor browser-based interactionADK Patterns Demonstrated
@tooldecoratoradk webcommandTest Plan
Manual Testing
Example Interaction
Commands:
exit/quit- Exit the assistantverbose- Toggle verbose tool output