forked from google/adk-python
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Drop-in Click replace for nicer CLI output #1
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
Open
ipv1337
wants to merge
1
commit into
main
Choose a base branch
from
feat/rich-click
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| * Add rich-click to pyproject.toml dependency '"rich-click>=1.8.8"' | ||
| * Replace all 'import click' with 'import rich_click as click' for drop in replacement | ||
|
|
||
| * git fetch https://github.com/google/adk-python.git main && git rebase FETCH_HEAD && git push -f origin feat/rich-click | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # ruff: noqa | ||
| """ | ||
| Software Engineer Agent. | ||
|
|
||
| This package provides an AI-powered software engineering assistant that helps with | ||
| various software development tasks including code reviews, design patterns, | ||
| testing, debugging, documentation, and DevOps. | ||
| """ | ||
|
|
||
| from . import agent |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| """ | ||
| Implementation of the Software Engineer Agent with knowledge and experience of sub-agents. | ||
|
|
||
| This is the main entry point for the software engineer agent. | ||
|
|
||
| It is a composite agent that uses the sub-agents to fulfill the user's request. | ||
| """ | ||
| import logging | ||
|
|
||
| from google.adk.agents import Agent | ||
| from google.adk.tools import load_memory | ||
|
|
||
| from . import prompt | ||
|
|
||
| # Use relative imports from the 'software_engineer' sibling directory | ||
| from .sub_agents.code_quality.agent import code_quality_agent | ||
| from .sub_agents.code_review.agent import code_review_agent | ||
| from .sub_agents.debugging.agent import debugging_agent | ||
| from .sub_agents.design_pattern.agent import design_pattern_agent | ||
| from .sub_agents.devops.agent import devops_agent | ||
| from .sub_agents.documentation.agent import documentation_agent | ||
| from .sub_agents.testing.agent import testing_agent | ||
| from .tools import ( | ||
| check_command_exists_tool, | ||
| check_shell_command_safety_tool, | ||
| codebase_search_tool, | ||
| configure_shell_approval_tool, | ||
| configure_shell_whitelist_tool, | ||
| edit_file_tool, | ||
| execute_vetted_shell_command_tool, | ||
| get_os_info_tool, | ||
| google_search_grounding, | ||
| list_dir_tool, | ||
| # load_memory_from_file_tool, # Remove placeholder | ||
| read_file_tool, | ||
| ) | ||
|
|
||
| # Import tools via the tools package __init__ | ||
| from .tools import ( | ||
| configure_approval_tool as configure_edit_approval_tool, # Keep alias for now | ||
| ) | ||
|
|
||
| # save_current_session_to_file_tool, # Remove placeholder | ||
| # Import memory tools (using the wrapped variable names) | ||
| from .tools.memory_tools import add_memory_fact, search_memory_facts | ||
| from .tools.project_context import load_project_context | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| # --- Memory Initialization --- | ||
| def initialize_session_memory(tool_context): | ||
| """Initializes the session memory in tool_context if it doesn't exist.""" | ||
| if not hasattr(tool_context, "session_state"): | ||
| logger.warning("Tool context does not have session_state. Cannot initialize memory.") | ||
| # In a real scenario, might need to initialize session_state itself | ||
| # For now, we assume session_state exists but memory might not. | ||
| return | ||
|
|
||
| if "memory" not in tool_context.session_state: | ||
| logger.info("Initializing agent session memory.") | ||
| tool_context.session_state["memory"] = { | ||
| "context": { | ||
| "project_path": None, # Will be populated by load_project_context | ||
| "current_file": None, | ||
| }, | ||
| "tasks": { | ||
| "active_task": None, | ||
| "completed_tasks": [], | ||
| }, | ||
| "history": { | ||
| "last_read_file": None, | ||
| "last_search_query": None, | ||
| "last_error": None, | ||
| }, | ||
| "user_preferences": {}, | ||
| # Add other relevant fields as needed based on agent interactions | ||
| } | ||
| # else: memory already exists, do nothing | ||
|
|
||
|
|
||
| # --- Agent Definition --- | ||
|
|
||
| # Note: Using custom ripgrep-based codebase search in tools/code_search.py | ||
|
|
||
| # REF: https://ai.google.dev/gemini-api/docs/rate-limits | ||
| root_agent = Agent( | ||
| model="gemini-2.5-flash-preview-04-17", | ||
| name="root_agent", | ||
| description="An AI software engineer assistant that helps with various software development tasks", | ||
| instruction=prompt.ROOT_AGENT_INSTR, | ||
| sub_agents=[ | ||
| design_pattern_agent, | ||
| documentation_agent, | ||
| code_review_agent, | ||
| code_quality_agent, | ||
| testing_agent, | ||
| debugging_agent, | ||
| devops_agent, # TODO: Move command tools to devops_agent with more guardrails | ||
| ], | ||
| tools=[ | ||
| read_file_tool, | ||
| list_dir_tool, | ||
| edit_file_tool, | ||
| configure_edit_approval_tool, | ||
| check_command_exists_tool, | ||
| check_shell_command_safety_tool, | ||
| configure_shell_approval_tool, | ||
| configure_shell_whitelist_tool, | ||
| execute_vetted_shell_command_tool, | ||
| google_search_grounding, | ||
| codebase_search_tool, | ||
| get_os_info_tool, | ||
| # Memory Tools: | ||
| load_memory, # Keep for transcript search | ||
| add_memory_fact, # Use wrapped tool variable name | ||
| search_memory_facts, # Use wrapped tool variable name | ||
| # Remove placeholder tools | ||
| # save_current_session_to_file_tool, | ||
| # load_memory_from_file_tool, | ||
| ], | ||
| # Pass the function directly, not as a list | ||
| before_agent_callback=load_project_context, | ||
| output_key="software_engineer", | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # ruff: noqa | ||
| """Defines the prompts for the software engineer agent.""" | ||
|
|
||
| ROOT_AGENT_INSTR = """ | ||
| - You are an autonomous principal software engineer assistant | ||
| - You help and lead developers with various software development tasks including code reviews, design patterns, testing, debugging, documentation, and DevOps | ||
| - You delegate tasks to the appropriate sub-agents based on the user's request | ||
| - Format your responses back to users with markdown. Use code blocks for file contents and code snippets, and bullets for lists. | ||
| - After every tool call, summarize the result and keep your response concise | ||
| - Please use only the agents and tools to fulfill all user requests | ||
| - If you do not know the answer, please first try to use the the shell command and then the `google_search_grounding` tool to find the information. | ||
|
|
||
| ## File System Interactions: | ||
| - To list files or directories, use the `list_directory_contents` tool. Provide the path. | ||
| - To read a file, use the `read_file_content` tool. Provide the path. | ||
| - **File Editing Approval:** By default, editing files requires user approval. You can change this setting for the current session using the `configure_edit_approval` tool. Call it with `require_approval=False` to disable approvals, or `require_approval=True` to enable them. | ||
| - **Editing/Creating Files:** To edit an existing file or create a new one, use the `edit_file_content` tool. Provide the `filepath` and the full `content`. | ||
| - If approval is required (default or enabled via `configure_edit_approval`), this tool will return a `pending_approval` status. You MUST then inform the user, show them the proposed path and content, and ask for confirmation. | ||
| - If the user approves, call `edit_file_content` again with the exact same `filepath` and `content`. | ||
| - If approval is *not* required (disabled via `configure_edit_approval`), the tool will write the file directly. | ||
|
|
||
| ## Shell Command Execution: | ||
| - **Available Tools:** | ||
| - `configure_shell_approval`: Enables or disables the need for user approval for NON-WHITELISTED commands (Default: enabled, `require_approval=True`). | ||
| - `configure_shell_whitelist`: Manages a list of commands that ALWAYS run directly, bypassing the approval check (Actions: `add`, `remove`, `list`, `clear`). A default set of safe commands is included. | ||
| - `check_command_exists_tool`: Verifies if a command is available in the environment before attempting execution. | ||
| - `check_shell_command_safety`: Checks if a specific command can run without explicit user approval based on the whitelist and approval settings. Returns status: `whitelisted`, `approval_disabled`, or `approval_required`. **Use this BEFORE attempting execution.** | ||
| - `execute_vetted_shell_command`: Executes a vetted shell command. This is the **ONLY** way to run shell commands. | ||
|
|
||
| - **Workflow for Running a Command (`<command_to_run>`):** | ||
| 1. **Check Existence:** Always run `check_command_exists_tool(command=<command_to_run>)` first. If it doesn't exist, inform the user and stop. | ||
| 2. **Check Safety:** Then, run `check_shell_command_safety(command=<command_to_run>)`. Review the safety analysis. If significant risks are identified, **DO NOT PROCEED** unless you have explicit user confirmation or a clear, safe alternative. Explain the risks. | ||
| 3. **Execute:** If checks pass, use `execute_vetted_shell_command(command=<command_to_run>, rationale=<brief_reasoning>)`. Provide a clear rationale. | ||
|
|
||
| ## Other Tools: | ||
| - If you cannot delegate the request to a sub-agent, or if the query is about a general topic you don't know, use the `google_search_grounding` tool to find the information. | ||
|
|
||
| ## Sub-Agent Delegation: | ||
| - First, try to delegate the request to the most relevant sub-agent based on the descriptions below. | ||
| - Inform the user that you are delegating the request to the sub-agent and the reason for the delegation. | ||
| - If the user asks for code review, transfer to the agent `code_review_agent` | ||
| - If the user asks for code quality analysis, static analysis, or quality improvements, transfer to the agent `code_quality_agent` | ||
| - If the user asks about design patterns or architecture, transfer to the agent `design_pattern_agent` | ||
| - If the user asks about testing, test generation, or test strategies, transfer to the agent `testing_agent` | ||
| - If the user asks for help with debugging or fixing errors, transfer to the agent `debugging_agent` | ||
| - If the user asks for help with documentation, transfer to the agent `documentation_agent` | ||
| - If the user asks about deployment, CI/CD, or DevOps practices, transfer to the agent `devops_agent` | ||
|
|
||
| ## Long-Term Memory Access: | ||
| - Your conversations contain ephemeral short-term memory. Discrete facts can be stored in long-term memory using specific tools. | ||
| - **Storing Facts:** When asked to remember a specific piece of information (like a preference, goal, or detail), you MUST use the `add_memory_fact` tool. Provide a concise `entity_name` (e.g., 'favorite_food', 'project_goal_api') and the `fact_content` to store. | ||
| - **Retrieving Facts:** To recall specific facts you were previously asked to remember, you MUST use the `search_memory_facts` tool. Provide a `query` describing the fact you need. | ||
| - This searches only the facts you explicitly stored. | ||
| - **Searching History:** To search the general conversation history for context or past discussions (not specific stored facts), use the `load_memory` tool with a natural language `query`. This searches transcripts. | ||
| - **Do not guess.** If asked about something you should have remembered, use `search_memory_facts`. If asked about general past discussion, use `load_memory`. | ||
|
|
||
| # --- Placeholder: Manual Memory Persistence Tools (Not Implemented) --- | ||
| # - TODO: The following tools are placeholders for a potential future feature | ||
| # - TODO: allowing manual persistence if the standard MemoryService is insufficient | ||
| # - TODO: for the 'adk run' environment. DO NOT USE THEM unless explicitly told | ||
| # - TODO: that they have been fully implemented. | ||
| # | ||
| # - `save_current_session_to_file(filepath: str)`: (Placeholder) Manually saves the state | ||
| # - of the *current* session to a JSON file (default: ./.manual_agent_memory.json). | ||
| # - Useful if you need to explicitly persist the current context for later use | ||
| # - outside the standard memory service. | ||
| # | ||
| # - `load_memory_from_file(query: str, filepath: str)`: (Placeholder) Manually loads | ||
| # - sessions from a JSON file (default: ./.manual_agent_memory.json) and searches | ||
| # - them based on the query. Use this *instead* of `load_memory` if specifically | ||
| # - instructed to load from the manual file. | ||
| # --- End Placeholder --- | ||
|
|
||
| Current user: | ||
| <user_profile> | ||
| {user_profile} | ||
| </user_profile> | ||
|
|
||
| Current project: | ||
| <project_context> | ||
| {project_context} | ||
| </project_context> | ||
| """ |
1 change: 1 addition & 0 deletions
1
contributing/samples/software_engineer_gemini/shared_libraries/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Shared libraries for the software engineer agent.""" |
123 changes: 123 additions & 0 deletions
123
contributing/samples/software_engineer_gemini/shared_libraries/types.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| """Type definitions for the software engineer agent.""" | ||
|
|
||
| from typing import List, Optional | ||
|
|
||
| from google.genai.types import GenerateContentConfig | ||
| from pydantic import BaseModel, Field | ||
|
|
||
| # Configure JSON response format | ||
| json_response_config = GenerateContentConfig( | ||
| temperature=0.2, | ||
| top_p=0.95, | ||
| candidate_count=1, | ||
| ) | ||
|
|
||
|
|
||
| # https://google.github.io/adk-docs/agents/llm-agents/#structuring-data-input_schema-output_schema-output_key | ||
|
|
||
|
|
||
| # Define data models for agent responses | ||
| class CodeIssue(BaseModel): | ||
| """Represents a code issue identified during code review.""" | ||
|
|
||
| issue_type: str = Field(description="Type of issue (bug, security, performance, style)") | ||
| severity: str = Field(description="Severity of the issue (critical, high, medium, low)") | ||
| location: str = Field(description="File and line number where the issue occurs") | ||
| description: str = Field(description="Detailed description of the issue") | ||
| recommendation: str = Field(description="Suggested fix or improvement") | ||
|
|
||
|
|
||
| class CodeReviewResponse(BaseModel): | ||
| """Response model for code review analysis.""" | ||
|
|
||
| issues: List[CodeIssue] = Field(description="List of identified code issues") | ||
| summary: str = Field(description="Overall summary of the code review") | ||
| suggestions: List[str] = Field(description="General suggestions for improvement") | ||
|
|
||
|
|
||
| class DesignPattern(BaseModel): | ||
| """Represents a design pattern recommendation.""" | ||
|
|
||
| pattern_name: str = Field(description="Name of the design pattern") | ||
| category: str = Field(description="Category of the pattern (creational, structural, behavioral)") | ||
| problem_solved: str = Field(description="What problem this pattern solves") | ||
| benefits: List[str] = Field(description="Benefits of using this pattern") | ||
| tradeoffs: List[str] = Field(description="Potential drawbacks or tradeoffs") | ||
| example_code: str = Field(description="Example implementation code") | ||
|
|
||
|
|
||
| class DesignPatternResponse(BaseModel): | ||
| """Response model for design pattern recommendations.""" | ||
|
|
||
| recommended_patterns: List[DesignPattern] = Field(description="List of recommended design patterns") | ||
| explanation: str = Field(description="Explanation of why these patterns are recommended") | ||
|
|
||
|
|
||
| class TestCase(BaseModel): | ||
| """Represents a test case.""" | ||
|
|
||
| name: str = Field(description="Name of the test case") | ||
| description: str = Field(description="Description of what the test verifies") | ||
| test_type: str = Field(description="Type of test (unit, integration, system)") | ||
| prerequisites: List[str] = Field(description="Prerequisites for running the test") | ||
| test_code: str = Field(description="The test code implementation") | ||
| expected_outcome: str = Field(description="Expected outcome of the test") | ||
|
|
||
|
|
||
| class TestingResponse(BaseModel): | ||
| """Response model for test generation.""" | ||
|
|
||
| test_cases: List[TestCase] = Field(description="List of generated test cases") | ||
| testing_strategy: str = Field(description="Overall testing strategy") | ||
| test_coverage: Optional[str] = Field(description="Expected test coverage") | ||
|
|
||
|
|
||
| class DebuggingStep(BaseModel): | ||
| """Represents a debugging step.""" | ||
|
|
||
| step_number: int = Field(description="Step number in the debugging process") | ||
| description: str = Field(description="Description of the debugging step") | ||
| expected_outcome: str = Field(description="What to look for or expect from this step") | ||
| code_example: Optional[str] = Field(description="Example code for this debugging step") | ||
|
|
||
|
|
||
| class DebuggingResponse(BaseModel): | ||
| """Response model for debugging assistance.""" | ||
|
|
||
| problem_analysis: str = Field(description="Analysis of the problem") | ||
| root_cause: Optional[str] = Field(description="Identified root cause") | ||
| debugging_steps: List[DebuggingStep] = Field(description="Steps to debug the issue") | ||
| solution: Optional[str] = Field(description="Proposed solution") | ||
|
|
||
|
|
||
| class DocumentationItem(BaseModel): | ||
| """Represents a documentation item.""" | ||
|
|
||
| title: str = Field(description="Title of the documentation item") | ||
| content: str = Field(description="Content of the documentation") | ||
| doc_type: str = Field(description="Type of documentation (README, API doc, inline comment)") | ||
| format: str = Field(description="Format of the documentation (Markdown, reStructuredText, etc.)") | ||
|
|
||
|
|
||
| class DocumentationResponse(BaseModel): | ||
| """Response model for documentation generation.""" | ||
|
|
||
| documentation_items: List[DocumentationItem] = Field(description="List of documentation items") | ||
| suggestions: Optional[List[str]] = Field(description="Suggestions for improving documentation") | ||
|
|
||
|
|
||
| class DevOpsComponent(BaseModel): | ||
| """Represents a DevOps component recommendation.""" | ||
|
|
||
| component_name: str = Field(description="Name of the DevOps component") | ||
| purpose: str = Field(description="Purpose of this component") | ||
| implementation: str = Field(description="Implementation details or configuration") | ||
| alternatives: Optional[List[str]] = Field(description="Alternative options") | ||
|
|
||
|
|
||
| class DevOpsResponse(BaseModel): | ||
| """Response model for DevOps recommendations.""" | ||
|
|
||
| components: List[DevOpsComponent] = Field(description="List of DevOps components") | ||
| implementation_plan: str = Field(description="Overall implementation plan") | ||
| resources: Optional[List[str]] = Field(description="Helpful resources or documentation") |
1 change: 1 addition & 0 deletions
1
contributing/samples/software_engineer_gemini/sub_agents/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Sub-agents for the software engineer agent.""" |
1 change: 1 addition & 0 deletions
1
contributing/samples/software_engineer_gemini/sub_agents/code_quality/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Code quality sub-agent for analyzing code and suggesting improvements.""" |
31 changes: 31 additions & 0 deletions
31
contributing/samples/software_engineer_gemini/sub_agents/code_quality/agent.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| """Code quality agent implementation.""" | ||
|
|
||
| from google.adk.agents import Agent | ||
| from google.genai.types import GenerateContentConfig | ||
|
|
||
| from ...tools.code_analysis import ( | ||
| analyze_code_tool, | ||
| get_analysis_issues_by_severity_tool, | ||
| suggest_code_fixes_tool, | ||
| ) | ||
| from ...tools.filesystem import list_dir_tool, read_file_tool | ||
| from . import prompt | ||
|
|
||
| code_quality_agent = Agent( | ||
| model="gemini-2.5-flash-preview-04-17", | ||
| name="code_quality_agent", | ||
| description="Analyzes code for quality issues and suggests improvements", | ||
| instruction=prompt.CODE_QUALITY_AGENT_INSTR, | ||
| tools=[ | ||
| analyze_code_tool, | ||
| get_analysis_issues_by_severity_tool, | ||
| suggest_code_fixes_tool, | ||
| read_file_tool, | ||
| list_dir_tool, | ||
| ], | ||
| generate_content_config=GenerateContentConfig( | ||
| temperature=0.1, | ||
| top_p=0.95, | ||
| max_output_tokens=4096, | ||
| ), | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This file appears to contain development notes and git commands. Such files are typically not committed to the source repository. Please consider removing this file from the pull request. If these notes are important for contributors, they could be moved to a more appropriate place like a wiki or a task in an issue tracker.