Skip to content

Commit b23deeb

Browse files
xuanyang15copybara-github
authored andcommitted
docs: Update adk docs update workflow to invoke the updater agent once per suggestion
Co-authored-by: Xuan Yang <xygoogle@google.com> PiperOrigin-RevId: 842789476
1 parent 51a638b commit b23deeb

File tree

2 files changed

+119
-11
lines changed

2 files changed

+119
-11
lines changed

contributing/samples/adk_documentation/adk_docs_updater/main.py

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
from adk_documentation.settings import DOC_REPO
2525
from adk_documentation.tools import get_issue
2626
from adk_documentation.utils import call_agent_async
27+
from adk_documentation.utils import parse_suggestions
2728
from google.adk.cli.utils import logs
2829
from google.adk.runners import InMemoryRunner
2930

3031
APP_NAME = "adk_docs_updater"
3132
USER_ID = "adk_docs_updater_user"
3233

33-
logs.setup_adk_logger(level=logging.DEBUG)
34+
logs.setup_adk_logger(level=logging.INFO)
3435

3536

3637
def process_arguments():
@@ -68,23 +69,84 @@ async def main():
6869
print(f"Failed to get issue {issue_number}: {get_issue_response}\n")
6970
return
7071
issue = get_issue_response["issue"]
72+
issue_title = issue.get("title", "")
73+
issue_body = issue.get("body", "")
74+
75+
# Parse numbered suggestions from issue body
76+
suggestions = parse_suggestions(issue_body)
77+
78+
if not suggestions:
79+
print(f"No numbered suggestions found in issue #{issue_number}.")
80+
print("Falling back to processing the entire issue as a single task.")
81+
suggestions = [(1, issue_body)]
82+
83+
print(f"Found {len(suggestions)} suggestion(s) in issue #{issue_number}.")
84+
print("=" * 80)
7185

7286
runner = InMemoryRunner(
7387
agent=agent.root_agent,
7488
app_name=APP_NAME,
7589
)
76-
session = await runner.session_service.create_session(
77-
app_name=APP_NAME,
78-
user_id=USER_ID,
79-
)
8090

81-
response = await call_agent_async(
82-
runner,
83-
USER_ID,
84-
session.id,
85-
f"Please update the ADK docs according to the following issue:\n{issue}",
91+
results = []
92+
for suggestion_num, suggestion_text in suggestions:
93+
print(f"\n>>> Processing suggestion #{suggestion_num}...")
94+
print("-" * 80)
95+
96+
# Create a new session for each suggestion to avoid context interference
97+
session = await runner.session_service.create_session(
98+
app_name=APP_NAME,
99+
user_id=USER_ID,
100+
)
101+
102+
prompt = f"""
103+
Please update the ADK docs according to suggestion #{suggestion_num} from issue #{issue_number}.
104+
105+
Issue title: {issue_title}
106+
107+
Suggestion to process:
108+
{suggestion_text}
109+
110+
Note: Focus only on this specific suggestion. Create exactly one pull request for this suggestion.
111+
"""
112+
113+
try:
114+
response = await call_agent_async(
115+
runner,
116+
USER_ID,
117+
session.id,
118+
prompt,
119+
)
120+
results.append({
121+
"suggestion_num": suggestion_num,
122+
"status": "success",
123+
"response": response,
124+
})
125+
print(f"<<<< Suggestion #{suggestion_num} completed.")
126+
except Exception as e:
127+
results.append({
128+
"suggestion_num": suggestion_num,
129+
"status": "error",
130+
"error": str(e),
131+
})
132+
print(f"<<<< Suggestion #{suggestion_num} failed: {e}")
133+
134+
print("-" * 80)
135+
136+
# Print summary
137+
print("\n" + "=" * 80)
138+
print("SUMMARY")
139+
print("=" * 80)
140+
successful = [r for r in results if r["status"] == "success"]
141+
failed = [r for r in results if r["status"] == "error"]
142+
print(
143+
f"Total: {len(results)}, Success: {len(successful)}, Failed:"
144+
f" {len(failed)}"
86145
)
87-
print(f"<<<< Agent Final Output: {response}\n")
146+
if failed:
147+
print("\nFailed suggestions:")
148+
for r in failed:
149+
print(f" - Suggestion #{r['suggestion_num']}: {r['error']}")
88150

89151

90152
if __name__ == "__main__":

contributing/samples/adk_documentation/utils.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import re
1516
from typing import Any
1617
from typing import Dict
1718
from typing import List
19+
from typing import Tuple
1820

1921
from adk_documentation.settings import GITHUB_TOKEN
2022
from google.adk.agents.run_config import RunConfig
@@ -96,3 +98,47 @@ async def call_agent_async(
9698
final_response_text += text
9799

98100
return final_response_text
101+
102+
103+
def parse_suggestions(issue_body: str) -> List[Tuple[int, str]]:
104+
"""Parse numbered suggestions from issue body.
105+
106+
Supports multiple formats:
107+
- Format A (markdown headers): "### 1. Title"
108+
- Format B (numbered list with bold): "1. **Title**"
109+
110+
Args:
111+
issue_body: The body text of the GitHub issue.
112+
113+
Returns:
114+
A list of tuples, where each tuple contains:
115+
- The suggestion number (1-based)
116+
- The full text of that suggestion
117+
"""
118+
# Try different patterns in order of preference
119+
patterns = [
120+
# Format A: "### 1. Title" (markdown header with number)
121+
(r"(?=^###\s+\d+\.)", r"^###\s+(\d+)\."),
122+
# Format B: "1. **Title**" (numbered list with bold)
123+
(r"(?=^\d+\.\s+\*\*)", r"^(\d+)\.\s+\*\*"),
124+
]
125+
126+
for split_pattern, match_pattern in patterns:
127+
parts = re.split(split_pattern, issue_body, flags=re.MULTILINE)
128+
129+
suggestions = []
130+
for part in parts:
131+
part = part.strip()
132+
if not part:
133+
continue
134+
135+
match = re.match(match_pattern, part)
136+
if match:
137+
suggestion_num = int(match.group(1))
138+
suggestions.append((suggestion_num, part))
139+
140+
# If we found suggestions with this pattern, return them
141+
if suggestions:
142+
return suggestions
143+
144+
return []

0 commit comments

Comments
 (0)