Skip to content

Commit 489648a

Browse files
authored
Merge branch 'main' into patch-1
2 parents 6aa880c + 9704d27 commit 489648a

File tree

27 files changed

+1265
-160
lines changed

27 files changed

+1265
-160
lines changed

.github/copybara-pr-handler.yml

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
name: Copybara PR Handler
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
inputs:
9+
pr_number:
10+
description: 'PR number to close (for testing)'
11+
required: true
12+
type: string
13+
commit_sha:
14+
description: 'Commit SHA reference (optional, for testing)'
15+
required: false
16+
type: string
17+
18+
jobs:
19+
close-imported-pr:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
pull-requests: write
23+
issues: write
24+
contents: read
25+
26+
steps:
27+
- name: Check for Copybara commits and close PRs
28+
uses: actions/github-script@v7
29+
with:
30+
github-token: ${{ secrets.ADK_TRIAGE_AGENT }}
31+
script: |
32+
// Check if this is a manual test run
33+
const isManualRun = context.eventName === 'workflow_dispatch';
34+
35+
let prsToClose = [];
36+
37+
if (isManualRun) {
38+
// Manual testing mode
39+
const prNumber = parseInt(context.payload.inputs.pr_number);
40+
const commitSha = context.payload.inputs.commit_sha || context.sha.substring(0, 7);
41+
42+
console.log('=== MANUAL TEST MODE ===');
43+
console.log(`Testing with PR #${prNumber}, commit ${commitSha}`);
44+
45+
prsToClose.push({ prNumber, commitSha });
46+
} else {
47+
// Normal mode: process commits from push event
48+
const commits = context.payload.commits || [];
49+
console.log(`Found ${commits.length} commit(s) in this push`);
50+
51+
// Process each commit
52+
for (const commit of commits) {
53+
const sha = commit.id;
54+
const committer = commit.committer.name;
55+
const message = commit.message;
56+
57+
console.log(`\n--- Processing commit ${sha.substring(0, 7)} ---`);
58+
console.log(`Committer: ${committer}`);
59+
60+
// Check if this is a Copybara commit
61+
if (committer !== 'Copybara-Service') {
62+
console.log('Not a Copybara commit, skipping');
63+
continue;
64+
}
65+
66+
// Extract PR number from commit message
67+
// Pattern: "Merge https://github.com/google/adk-python/pull/3333"
68+
const prMatch = message.match(/Merge https:\/\/github\.com\/google\/adk-python\/pull\/(\d+)/);
69+
70+
if (!prMatch) {
71+
console.log('No PR number found in Copybara commit message');
72+
continue;
73+
}
74+
75+
const prNumber = parseInt(prMatch[1]);
76+
const commitSha = sha.substring(0, 7);
77+
78+
prsToClose.push({ prNumber, commitSha });
79+
}
80+
}
81+
82+
// Process PRs to close
83+
for (const { prNumber, commitSha } of prsToClose) {
84+
console.log(`\n--- Processing PR #${prNumber} ---`);
85+
86+
// Get PR details to check if it's open
87+
let pr;
88+
try {
89+
pr = await github.rest.pulls.get({
90+
owner: context.repo.owner,
91+
repo: context.repo.repo,
92+
pull_number: prNumber
93+
});
94+
} catch (error) {
95+
console.log(`PR #${prNumber} not found or inaccessible:`, error.message);
96+
continue;
97+
}
98+
99+
// Only close if PR is still open
100+
if (pr.data.state !== 'open') {
101+
console.log(`PR #${prNumber} is already ${pr.data.state}, skipping`);
102+
continue;
103+
}
104+
105+
const author = pr.data.user.login;
106+
107+
try {
108+
// Add comment with commit reference
109+
await github.rest.issues.createComment({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
issue_number: prNumber,
113+
body: `Thank you @${author} for your contribution! 🎉\n\nYour changes have been successfully imported and merged via Copybara in commit ${commitSha}.\n\nClosing this PR as the changes are now in the main branch.`
114+
});
115+
116+
// Close the PR
117+
await github.rest.pulls.update({
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
pull_number: prNumber,
121+
state: 'closed'
122+
});
123+
124+
console.log(`Successfully closed PR #${prNumber}`);
125+
} catch (error) {
126+
console.log(`Error closing PR #${prNumber}:`, error.message);
127+
}
128+
}
129+
130+
if (isManualRun) {
131+
console.log('\n=== TEST COMPLETED ===');
132+
} else {
133+
console.log('\n--- Finished processing all commits ---');
134+
}

contributing/samples/adk_agent_builder_assistant/agent_builder_assistant.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
from google.adk.tools import FunctionTool
2727
from google.genai import types
2828

29-
from .sub_agents.adk_knowledge_agent import create_adk_knowledge_agent
3029
from .sub_agents.google_search_agent import create_google_search_agent
3130
from .sub_agents.url_context_agent import create_url_context_agent
3231
from .tools.cleanup_unused_files import cleanup_unused_files
3332
from .tools.delete_files import delete_files
3433
from .tools.explore_project import explore_project
3534
from .tools.read_config_files import read_config_files
3635
from .tools.read_files import read_files
36+
from .tools.search_adk_knowledge import search_adk_knowledge
3737
from .tools.search_adk_source import search_adk_source
3838
from .tools.write_config_files import write_config_files
3939
from .tools.write_files import write_files
@@ -69,11 +69,9 @@ def create_agent(
6969
# - Maintains compatibility with existing ADK tool ecosystem
7070

7171
# Built-in ADK tools wrapped as sub-agents
72-
adk_knowledge_agent = create_adk_knowledge_agent()
7372
google_search_agent = create_google_search_agent()
7473
url_context_agent = create_url_context_agent()
7574
agent_tools = [
76-
AgentTool(adk_knowledge_agent),
7775
AgentTool(google_search_agent),
7876
AgentTool(url_context_agent),
7977
]
@@ -99,6 +97,8 @@ def create_agent(
9997
FunctionTool(cleanup_unused_files),
10098
# ADK source code search (regex-based)
10199
FunctionTool(search_adk_source), # Search ADK source with regex
100+
# ADK knowledge search
101+
FunctionTool(search_adk_knowledge), # Search ADK knowledge base
102102
]
103103

104104
# Combine all tools

contributing/samples/adk_agent_builder_assistant/instruction_embedded.template

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,9 @@ tools:
272272

273273
### ADK Knowledge and Research Tools
274274

275-
**Default research tool**: Use `adk_knowledge_agent` first for ADK concepts, APIs,
275+
**Default research tool**: Use `search_adk_knowledge` first for ADK concepts, APIs,
276276
examples, and troubleshooting. Switch to the tools below only when the
277-
knowledge agent lacks the needed information.
277+
knowledge base lacks the needed information.
278278

279279
- `search_adk_source`: Regex search across ADK source for classes, methods, and
280280
signatures; follow up with `read_files` for full context.
@@ -287,7 +287,7 @@ need agent-type clarification, want best practices, hit errors, express
287287
uncertainty about architecture, or you otherwise need authoritative guidance.
288288

289289
**Recommended research sequence** (stop once you have enough information):
290-
1. `adk_knowledge_agent`
290+
1. `search_adk_knowledge`
291291
2. `search_adk_source` → `read_files`
292292
3. `google_search_agent`
293293
4. `url_context_agent`

contributing/samples/adk_agent_builder_assistant/sub_agents/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414

1515
"""Sub-agents for Agent Builder Assistant."""
1616

17-
from .adk_knowledge_agent import create_adk_knowledge_agent
1817
from .google_search_agent import create_google_search_agent
1918
from .url_context_agent import create_url_context_agent
2019

2120
__all__ = [
22-
'create_adk_knowledge_agent',
2321
'create_google_search_agent',
2422
'create_url_context_agent',
2523
]

contributing/samples/adk_agent_builder_assistant/sub_agents/adk_knowledge_agent.py

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""ADK knowledge search tool."""
16+
17+
from typing import Any
18+
import uuid
19+
20+
import requests
21+
22+
KNOWLEDGE_SERVICE_APP_URL = "https://adk-agent-builder-knowledge-service-654646711756.us-central1.run.app"
23+
KNOWLEDGE_SERVICE_APP_NAME = "adk_knowledge_agent"
24+
KNOWLEDGE_SERVICE_APP_USER_NAME = "agent_builder_assistant"
25+
26+
HEADERS = {
27+
"Content-Type": "application/json",
28+
"Accept": "application/json",
29+
}
30+
31+
32+
def search_adk_knowledge(
33+
query: str,
34+
) -> dict[str, Any]:
35+
"""Searches ADK knowledge base for relevant information.
36+
37+
Args:
38+
query: The query to search in ADK knowledge base.
39+
40+
Returns:
41+
A dict with status and the response from the knowledge service.
42+
"""
43+
# Create a new session
44+
session_id = uuid.uuid4()
45+
create_session_url = f"{KNOWLEDGE_SERVICE_APP_URL}/apps/{KNOWLEDGE_SERVICE_APP_NAME}/users/{KNOWLEDGE_SERVICE_APP_USER_NAME}/sessions/{session_id}"
46+
47+
try:
48+
create_session_response = post_request(
49+
create_session_url,
50+
{},
51+
)
52+
except requests.exceptions.RequestException as e:
53+
return error_response(f"Failed to create session: {e}")
54+
session_id = create_session_response["id"]
55+
56+
# Search ADK knowledge base
57+
search_url = f"{KNOWLEDGE_SERVICE_APP_URL}/run"
58+
try:
59+
search_response = post_request(
60+
search_url,
61+
{
62+
"app_name": KNOWLEDGE_SERVICE_APP_NAME,
63+
"user_id": KNOWLEDGE_SERVICE_APP_USER_NAME,
64+
"session_id": session_id,
65+
"new_message": {"role": "user", "parts": [{"text": query}]},
66+
},
67+
)
68+
except requests.exceptions.RequestException as e:
69+
return error_response(f"Failed to search ADK knowledge base: {e}")
70+
return {
71+
"status": "success",
72+
"response": search_response,
73+
}
74+
75+
76+
def error_response(error_message: str) -> dict[str, Any]:
77+
"""Returns an error response."""
78+
return {"status": "error", "error_message": error_message}
79+
80+
81+
def post_request(url: str, payload: dict[str, Any]) -> dict[str, Any]:
82+
"""Executes a POST request."""
83+
response = requests.post(url, headers=HEADERS, json=payload, timeout=60)
84+
response.raise_for_status()
85+
return response.json()

contributing/samples/bigquery/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ distributed via the `google.adk.tools.bigquery` module. These tools include:
2121

2222
Fetches metadata about a BigQuery table.
2323

24+
5. `get_job_info`
25+
Fetches metadata about a BigQuery job.
26+
2427
5. `execute_sql`
2528

2629
Runs or dry-runs a SQL query in BigQuery.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# JSON Passing Agent
2+
3+
This sample demonstrates how to pass structured JSON data between agents. The example uses a pizza ordering scenario where one agent takes the order and passes it to another agent for confirmation.
4+
5+
## How to run
6+
7+
1. Run the agent:
8+
```bash
9+
adk run .
10+
```
11+
12+
2. Talk to the agent:
13+
```
14+
I want to order a pizza
15+
```
16+
17+
## Example conversation
18+
```
19+
[user]: I'd like a large pizza with pepperoni and mushrooms on a thin crust.
20+
[order_intake_agent]: (tool call to get available sizes, crusts, toppings)
21+
[order_intake_agent]: (returns a PizzaOrder JSON)
22+
[order_confirmation_agent]: (tool call to calculate_price)
23+
[order_confirmation_agent]: You ordered a large thin crust pizza with pepperoni and mushrooms. The total price is $15.00.
24+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent

0 commit comments

Comments
 (0)