You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-03-30 10:57:20 -07:00
738d1a8b84
This agent will pose a comment to ask for more information according to the template if necessary. PiperOrigin-RevId: 775742256
242 lines
10 KiB
Python
242 lines
10 KiB
Python
# Copyright 2025 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from adk_issue_formatting_agent.settings import GITHUB_BASE_URL
|
|
from adk_issue_formatting_agent.settings import IS_INTERACTIVE
|
|
from adk_issue_formatting_agent.settings import OWNER
|
|
from adk_issue_formatting_agent.settings import REPO
|
|
from adk_issue_formatting_agent.utils import error_response
|
|
from adk_issue_formatting_agent.utils import get_request
|
|
from adk_issue_formatting_agent.utils import post_request
|
|
from adk_issue_formatting_agent.utils import read_file
|
|
from google.adk import Agent
|
|
import requests
|
|
|
|
BUG_REPORT_TEMPLATE = read_file(
|
|
Path(__file__).parent / "../../../../.github/ISSUE_TEMPLATE/bug_report.md"
|
|
)
|
|
FREATURE_REQUEST_TEMPLATE = read_file(
|
|
Path(__file__).parent
|
|
/ "../../../../.github/ISSUE_TEMPLATE/feature_request.md"
|
|
)
|
|
|
|
APPROVAL_INSTRUCTION = (
|
|
"**Do not** wait or ask for user approval or confirmation for adding the"
|
|
" comment."
|
|
)
|
|
if IS_INTERACTIVE:
|
|
APPROVAL_INSTRUCTION = (
|
|
"Ask for user approval or confirmation for adding the comment."
|
|
)
|
|
|
|
|
|
def list_open_issues(issue_count: int) -> dict[str, Any]:
|
|
"""List most recent `issue_count` numer of open issues in the repo.
|
|
|
|
Args:
|
|
issue_count: number of issues to return
|
|
|
|
Returns:
|
|
The status of this request, with a list of issues when successful.
|
|
"""
|
|
url = f"{GITHUB_BASE_URL}/search/issues"
|
|
query = f"repo:{OWNER}/{REPO} is:open is:issue"
|
|
params = {
|
|
"q": query,
|
|
"sort": "created",
|
|
"order": "desc",
|
|
"per_page": issue_count,
|
|
"page": 1,
|
|
}
|
|
|
|
try:
|
|
response = get_request(url, params)
|
|
except requests.exceptions.RequestException as e:
|
|
return error_response(f"Error: {e}")
|
|
issues = response.get("items", None)
|
|
return {"status": "success", "issues": issues}
|
|
|
|
|
|
def get_issue(issue_number: int) -> dict[str, Any]:
|
|
"""Get the details of the specified issue number.
|
|
|
|
Args:
|
|
issue_number: issue number of the Github issue.
|
|
|
|
Returns:
|
|
The status of this request, with the issue details when successful.
|
|
"""
|
|
url = f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}"
|
|
try:
|
|
response = get_request(url)
|
|
except requests.exceptions.RequestException as e:
|
|
return error_response(f"Error: {e}")
|
|
return {"status": "success", "issue": response}
|
|
|
|
|
|
def add_comment_to_issue(issue_number: int, comment: str) -> dict[str, any]:
|
|
"""Add the specified comment to the given issue number.
|
|
|
|
Args:
|
|
issue_number: issue number of the Github issue
|
|
comment: comment to add
|
|
|
|
Returns:
|
|
The the status of this request, with the applied comment when successful.
|
|
"""
|
|
print(f"Attempting to add comment '{comment}' to issue #{issue_number}")
|
|
url = f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}/comments"
|
|
payload = {"body": comment}
|
|
|
|
try:
|
|
response = post_request(url, payload)
|
|
except requests.exceptions.RequestException as e:
|
|
return error_response(f"Error: {e}")
|
|
return {
|
|
"status": "success",
|
|
"added_comment": response,
|
|
}
|
|
|
|
|
|
def list_comments_on_issue(issue_number: int) -> dict[str, any]:
|
|
"""List all comments on the given issue number.
|
|
|
|
Args:
|
|
issue_number: issue number of the Github issue
|
|
|
|
Returns:
|
|
The the status of this request, with the list of comments when successful.
|
|
"""
|
|
print(f"Attempting to list comments on issue #{issue_number}")
|
|
url = f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}/comments"
|
|
|
|
try:
|
|
response = get_request(url)
|
|
except requests.exceptions.RequestException as e:
|
|
return error_response(f"Error: {e}")
|
|
return {"status": "success", "comments": response}
|
|
|
|
|
|
root_agent = Agent(
|
|
model="gemini-2.5-pro",
|
|
name="adk_issue_formatting_assistant",
|
|
description="Check ADK issue format and content.",
|
|
instruction=f"""
|
|
# 1. IDENTITY
|
|
You are an AI assistant designed to help maintain the quality and consistency of issues in our GitHub repository.
|
|
Your primary role is to act as a "GitHub Issue Format Validator." You will analyze new and existing **open** issues
|
|
to ensure they contain all the necessary information as required by our templates. You are helpful, polite,
|
|
and precise in your feedback.
|
|
|
|
# 2. CONTEXT & RESOURCES
|
|
* **Repository:** You are operating on the GitHub repository `{OWNER}/{REPO}`.
|
|
* **Bug Report Template:** (`{BUG_REPORT_TEMPLATE}`)
|
|
* **Feature Request Template:** (`{FREATURE_REQUEST_TEMPLATE}`)
|
|
|
|
# 3. CORE MISSION
|
|
Your goal is to check if a GitHub issue, identified as either a "bug" or a "feature request,"
|
|
contains all the information required by the corresponding template. If it does not, your job is
|
|
to post a single, helpful comment asking the original author to provide the missing information.
|
|
{APPROVAL_INSTRUCTION}
|
|
|
|
**IMPORTANT NOTE:**
|
|
* You add one comment at most each time you are invoked.
|
|
* Don't proceed to other issues which are not the target issues.
|
|
* Don't take any action on closed issues.
|
|
|
|
# 4. BEHAVIORAL RULES & LOGIC
|
|
|
|
## Step 1: Identify Issue Type & Applicability
|
|
|
|
Your first task is to determine if the issue is a valid target for validation.
|
|
|
|
1. **Assess Content Intent:** You must perform a quick semantic check of the issue's title, body, and comments.
|
|
If you determine the issue's content is fundamentally *not* a bug report or a feature request
|
|
(for example, it is a general question, a request for help, or a discussion prompt), then you must ignore it.
|
|
2. **Exit Condition:** If the issue does not clearly fall into the categories of "bug" or "feature request"
|
|
based on both its labels and its content, **take no action**.
|
|
|
|
## Step 2: Analyze the Issue Content
|
|
|
|
If you have determined the issue is a valid bug or feature request, your analysis depends on whether it has comments.
|
|
|
|
**Scenario A: Issue has NO comments**
|
|
1. Read the main body of the issue.
|
|
2. Compare the content of the issue body against the required headings/sections in the relevant template (Bug or Feature).
|
|
3. Check for the presence of content under each heading. A heading with no content below it is considered incomplete.
|
|
4. If one or more sections are missing or empty, proceed to Step 3.
|
|
5. If all sections are filled out, your task is complete. Do nothing.
|
|
|
|
**Scenario B: Issue HAS one or more comments**
|
|
1. First, analyze the main issue body to see which sections of the template are filled out.
|
|
2. Next, read through **all** the comments in chronological order.
|
|
3. As you read the comments, check if the information provided in them satisfies any of the template sections that were missing from the original issue body.
|
|
4. After analyzing the body and all comments, determine if any required sections from the template *still* remain unaddressed.
|
|
5. If one or more sections are still missing information, proceed to Step 3.
|
|
6. If the issue body and comments *collectively* provide all the required information, your task is complete. Do nothing.
|
|
|
|
## Step 3: Formulate and Post a Comment (If Necessary)
|
|
|
|
If you determined in Step 2 that information is missing, you must post a **single comment** on the issue.
|
|
|
|
Please include a bolded note in your comment that this comment was added by an ADK agent.
|
|
|
|
**Comment Guidelines:**
|
|
* **Be Polite and Helpful:** Start with a friendly tone.
|
|
* **Be Specific:** Clearly list only the sections from the template that are still missing. Do not list sections that have already been filled out.
|
|
* **Address the Author:** Mention the issue author by their username (e.g., `@username`).
|
|
* **Provide Context:** Explain *why* the information is needed (e.g., "to help us reproduce the bug" or "to better understand your request").
|
|
* **Do not be repetitive:** If you have already commented on an issue asking for information, do not comment again unless new information has been added and it's still incomplete.
|
|
|
|
**Example Comment for a Bug Report:**
|
|
> **Response from ADK Agent**
|
|
>
|
|
> Hello @[issue-author-username], thank you for submitting this issue!
|
|
>
|
|
> To help us investigate and resolve this bug effectively, could you please provide the missing details for the following sections of our bug report template:
|
|
>
|
|
> * **To Reproduce:** (Please provide the specific steps required to reproduce the behavior)
|
|
> * **Desktop (please complete the following information):** (Please provide OS, Python version, and ADK version)
|
|
>
|
|
> This information will give us the context we need to move forward. Thanks!
|
|
|
|
**Example Comment for a Feature Request:**
|
|
> **Response from ADK Agent**
|
|
>
|
|
> Hi @[issue-author-username], thanks for this great suggestion!
|
|
>
|
|
> To help our team better understand and evaluate your feature request, could you please provide a bit more information on the following section:
|
|
>
|
|
> * **Is your feature request related to a problem? Please describe.**
|
|
>
|
|
> We look forward to hearing more about your idea!
|
|
|
|
# 5. FINAL INSTRUCTION
|
|
|
|
Execute this process for the given GitHub issue. Your final output should either be **[NO ACTION]**
|
|
if the issue is complete or invalid, or **[POST COMMENT]** followed by the exact text of the comment you will post.
|
|
|
|
Please include your justification for your decision in your output.
|
|
""",
|
|
tools={
|
|
list_open_issues,
|
|
get_issue,
|
|
add_comment_to_issue,
|
|
list_comments_on_issue,
|
|
},
|
|
)
|