chore: import upstream snapshot with attribution
Continuous Integration / Pre-commit Linter (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.10) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.11) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.12) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.12) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Has been cancelled
Copybara PR Handler / close-imported-pr (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:25:13 +08:00
commit ec2b666284
2231 changed files with 491535 additions and 0 deletions
@@ -0,0 +1,15 @@
# Copyright 2026 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 . import agent
@@ -0,0 +1,122 @@
# Copyright 2026 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.
import os
import sys
SAMPLES_DIR = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
if SAMPLES_DIR not in sys.path:
sys.path.append(SAMPLES_DIR)
from adk_documentation.settings import CODE_OWNER
from adk_documentation.settings import CODE_REPO
from adk_documentation.settings import DOC_OWNER
from adk_documentation.settings import DOC_REPO
from adk_documentation.settings import IS_INTERACTIVE
from adk_documentation.settings import LOCAL_REPOS_DIR_PATH
from adk_documentation.tools import clone_or_pull_repo
from adk_documentation.tools import create_pull_request_from_changes
from adk_documentation.tools import get_issue
from adk_documentation.tools import list_directory_contents
from adk_documentation.tools import read_local_git_repo_file_content
from adk_documentation.tools import search_local_git_repo
from google.adk import Agent
if IS_INTERACTIVE:
APPROVAL_INSTRUCTION = (
"Ask for user approval or confirmation for creating the pull request."
)
else:
APPROVAL_INSTRUCTION = (
"**Do not** wait or ask for user approval or confirmation for creating"
" the pull request."
)
root_agent = Agent(
model="gemini-3.5-flash",
name="adk_docs_updater",
description=(
"Update the ADK docs based on the code in the ADK Python codebase"
" according to the instructions in the ADK docs issues."
),
instruction=f"""
# 1. Identity
You are a helper bot that updates ADK docs in GitHub Repository {DOC_OWNER}/{DOC_REPO}
based on the code in the ADK Python codebase in GitHub Repository {CODE_OWNER}/{CODE_REPO} according to the instructions in the ADK docs issues.
You are very familiar with GitHub, especially how to search for files in a GitHub repository using git grep.
# 2. Responsibilities
Your core responsibility includes:
- Read the doc update instructions in the ADK docs issues.
- Find **all** the related Python files in ADK Python codebase.
- Compare the ADK docs with **all** the related Python files and analyze the differences and the doc update instructions.
- Create a pull request to update the ADK docs.
# 3. Workflow
1. Always call the `clone_or_pull_repo` tool to make sure the ADK docs and codebase repos exist in the local folder {LOCAL_REPOS_DIR_PATH}/repo_name and are the latest version.
2. Read and analyze the issue specified by user.
- If user only specified the issue number, call the `get_issue` tool to get the issue details; otherwise, use the issue details provided by user directly.
3. If the issue contains instructions about how to update the ADK docs, follow the instructions to update the ADK docs.
4. Understand the doc update instructions.
- Ignore and skip the instructions about updating API reference docs, since it will be automatically generated by the ADK team.
5. Read the doc to update using the `read_local_git_repo_file_content` tool from the local ADK docs repo under {LOCAL_REPOS_DIR_PATH}/{DOC_REPO}.
6. Find the related Python files in the ADK Python codebase.
- If the doc update instructions specify paths to the Python files, use them directly; otherwise, use a list of regex search patterns to find the related Python files through the `search_local_git_repo` tool.
- You should focus on the main ADK Python codebase, ignore the changes in tests or other auxiliary files.
- You should find all the related Python files, not only the most relevant one.
7. Read the specified or found Python files using the `read_local_git_repo_file_content` tool to find all the related code.
- You can ignore unit test files, unless you are sure that the test code is useful to understand the related concepts.
- You should read all the found files to find all the related code, unless you already know the content of the file or you are sure that the file is not related to the ADK doc.
8. Update the ADK doc file according to the doc update instructions and the related code.
- Use active voice phrasing in your doc updates.
- Use second person "you" form of address in your doc updates.
9. Create pull requests to update the ADK doc file using the `create_pull_request_from_changes` tool.
- For each recommended change, create a separate pull request. Make sure the recommended change has exactly one pull request.
For example, if the ADK doc issue contains the following 2 recommended changes:
```
1. Title of recommended change 1
<content of recommended change 1>
2. Title of recommended change 2
<content of recommended change 2>
```
Then you should create 2 pull requests, one for each recommended change, even if each recommended change needs to update multiple ADK doc files.
- The title of the pull request should be "Update ADK doc according to issue #<issue number> - <change id>", where <issue number> is the number of the ADK docs issue and <change id> is the id of the recommended change (e.g. "1", "2", etc.).
- The body of the pull request should be the instructions about how to update the ADK docs.
- **{APPROVAL_INSTRUCTION}**
# 4. Guidelines & Rules
- **File Paths:** Always use absolute paths when calling the tools to read files, list directories, or search the codebase.
- **Tool Call Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Avoid deletion:** Do not delete any existing content unless specifically directed to do so.
- **Explanation:** Provide concise explanations for your actions and reasoning for each step.
- **Minimize changes:** When making updates to documentation pages, make the minimum amount of changes to achieve the communication goal. Only make changes that are necessary, and leave everything else as-is.
- **Avoid trivial code sample changes:** Update code samples only when adding or modifying functionality. Do not reformat code samples, change variable names, or change code syntax unless you are specifically directed to make those updates.
# 5. Output
Present the following in an easy to read format as the final output to the user.
- The actions you took and the reasoning
- The summary of the pull request created
""",
tools=[
clone_or_pull_repo,
list_directory_contents,
search_local_git_repo,
read_local_git_repo_file_content,
create_pull_request_from_changes,
get_issue,
],
)
@@ -0,0 +1,167 @@
# Copyright 2026 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.
import argparse
import asyncio
import logging
import time
from adk_documentation.adk_docs_updater import agent
from adk_documentation.settings import CODE_OWNER
from adk_documentation.settings import CODE_REPO
from adk_documentation.settings import DOC_OWNER
from adk_documentation.settings import DOC_REPO
from adk_documentation.tools import get_issue
from adk_documentation.utils import call_agent_async
from adk_documentation.utils import parse_suggestions
from google.adk.cli.utils import logs
from google.adk.runners import InMemoryRunner
APP_NAME = "adk_docs_updater"
USER_ID = "adk_docs_updater_user"
logs.setup_adk_logger(level=logging.INFO)
def process_arguments():
"""Parses command-line arguments."""
parser = argparse.ArgumentParser(
description="A script that creates pull requests to update ADK docs.",
epilog=(
"Example usage: \n"
"\tpython -m adk_docs_updater.main --issue_number 123\n"
),
formatter_class=argparse.RawTextHelpFormatter,
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--issue_number",
type=int,
metavar="NUM",
help="Answer a specific issue number.",
)
return parser.parse_args()
async def main():
args = process_arguments()
if not args.issue_number:
print("Please specify an issue number using --issue_number flag")
return
issue_number = args.issue_number
get_issue_response = get_issue(DOC_OWNER, DOC_REPO, issue_number)
if get_issue_response["status"] != "success":
print(f"Failed to get issue {issue_number}: {get_issue_response}\n")
return
issue = get_issue_response["issue"]
issue_title = issue.get("title", "")
issue_body = issue.get("body", "")
# Parse numbered suggestions from issue body
suggestions = parse_suggestions(issue_body)
if not suggestions:
print(f"No numbered suggestions found in issue #{issue_number}.")
print("Falling back to processing the entire issue as a single task.")
suggestions = [(1, issue_body)]
print(f"Found {len(suggestions)} suggestion(s) in issue #{issue_number}.")
print("=" * 80)
runner = InMemoryRunner(
agent=agent.root_agent,
app_name=APP_NAME,
)
results = []
for suggestion_num, suggestion_text in suggestions:
print(f"\n>>> Processing suggestion #{suggestion_num}...")
print("-" * 80)
# Create a new session for each suggestion to avoid context interference
session = await runner.session_service.create_session(
app_name=APP_NAME,
user_id=USER_ID,
)
prompt = f"""
Please update the ADK docs according to suggestion #{suggestion_num} from issue #{issue_number}.
Issue title: {issue_title}
Suggestion to process:
{suggestion_text}
Note: Focus only on this specific suggestion. Create exactly one pull request for this suggestion.
"""
try:
response = await call_agent_async(
runner,
USER_ID,
session.id,
prompt,
)
results.append({
"suggestion_num": suggestion_num,
"status": "success",
"response": response,
})
print(f"<<<< Suggestion #{suggestion_num} completed.")
except Exception as e:
results.append({
"suggestion_num": suggestion_num,
"status": "error",
"error": str(e),
})
print(f"<<<< Suggestion #{suggestion_num} failed: {e}")
print("-" * 80)
# Print summary
print("\n" + "=" * 80)
print("SUMMARY")
print("=" * 80)
successful = [r for r in results if r["status"] == "success"]
failed = [r for r in results if r["status"] == "error"]
print(
f"Total: {len(results)}, Success: {len(successful)}, Failed:"
f" {len(failed)}"
)
if failed:
print("\nFailed suggestions:")
for r in failed:
print(f" - Suggestion #{r['suggestion_num']}: {r['error']}")
if __name__ == "__main__":
start_time = time.time()
print(
f"Start creating pull requests to update {DOC_OWNER}/{DOC_REPO} docs"
f" according the {CODE_OWNER}/{CODE_REPO} at"
f" {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(start_time))}"
)
print("-" * 80)
asyncio.run(main())
print("-" * 80)
end_time = time.time()
print(
"Updating finished at"
f" {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(end_time))}",
)
print("Total script execution time:", f"{end_time - start_time:.2f} seconds")