Skip to content

Commit 8208a9a

Browse files
Merge branch 'main' into fix/issue-span-attributes
2 parents b73be84 + 1063fa5 commit 8208a9a

File tree

32 files changed

+1630
-241
lines changed

32 files changed

+1630
-241
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,69 @@ assignees: ''
77

88
---
99

10-
** Please make sure you read the contribution guide and file the issues in the right place. **
11-
[Contribution guide.](https://google.github.io/adk-docs/contributing-guide/)
10+
## 🔴 Required Information
11+
*Please ensure all items in this section are completed to allow for efficient
12+
triaging. Requests without complete information may be rejected / deprioritized.
13+
If an item is not applicable to you - please mark it as N/A*
1214

13-
**Describe the bug**
15+
**Describe the Bug:**
1416
A clear and concise description of what the bug is.
1517

16-
**To Reproduce**
17-
Please share a minimal code and data to reproduce your problem.
18-
Steps to reproduce the behavior:
18+
**Steps to Reproduce:**
19+
Please provide a numbered list of steps to reproduce the behavior:
1920
1. Install '...'
2021
2. Run '....'
2122
3. Open '....'
2223
4. Provide error or stacktrace
2324

24-
**Expected behavior**
25+
**Expected Behavior:**
2526
A clear and concise description of what you expected to happen.
2627

27-
**Screenshots**
28-
If applicable, add screenshots to help explain your problem.
28+
**Observed Behavior:**
29+
What actually happened? Include error messages or crash stack traces here.
2930

30-
**Desktop (please complete the following information):**
31-
- OS: [e.g. macOS, Linux, Windows]
32-
- Python version(python -V):
33-
- ADK version(pip show google-adk):
31+
**Environment Details:**
32+
33+
- ADK Library Version (pip show google-adk):
34+
- Desktop OS:** [e.g., macOS, Linux, Windows]
35+
- Python Version (python -V):
36+
37+
**Model Information:**
3438

35-
**Model Information:**
3639
- Are you using LiteLLM: Yes/No
37-
- Which model is being used(e.g. gemini-2.5-pro)
40+
- Which model is being used: (e.g., gemini-2.5-pro)
41+
42+
---
43+
44+
## 🟡 Optional Information
45+
*Providing this information greatly speeds up the resolution process.*
46+
47+
**Regression:**
48+
Did this work in a previous version of ADK? If so, which one?
3849

39-
**Additional context**
50+
**Logs:**
51+
Please attach relevant logs. Wrap them in code blocks (```) or attach a
52+
text file.
53+
```text
54+
// Paste logs here
55+
```
56+
57+
**Screenshots / Video:**
58+
If applicable, add screenshots or screen recordings to help explain
59+
your problem.
60+
61+
**Additional Context:**
4062
Add any other context about the problem here.
63+
64+
**Minimal Reproduction Code:**
65+
Please provide a code snippet or a link to a Gist/repo that isolates the issue.
66+
```python
67+
// Code snippet here
68+
```
69+
70+
**How often has this issue occurred?:**
71+
72+
- Always (100%)
73+
- Often (50%+)
74+
- Intermittently (<50%)
75+
- Once / Rare

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,39 @@ assignees: ''
1010
** Please make sure you read the contribution guide and file the issues in the right place. **
1111
[Contribution guide.](https://google.github.io/adk-docs/contributing-guide/)
1212

13-
**Is your feature request related to a problem? Please describe.**
14-
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
13+
## 🔴 Required Information
14+
*Please ensure all items in this section are completed to allow for efficient
15+
triaging. Requests without complete information may be rejected / deprioritized.
16+
If an item is not applicable to you - please mark it as N/A*
1517

16-
**Describe the solution you'd like**
17-
A clear and concise description of what you want to happen.
18+
### Is your feature request related to a specific problem?
19+
Please describe the problem you are trying to solve. (Ex: "I'm always frustrated
20+
when I have to manually handle X...")
1821

19-
**Describe alternatives you've considered**
20-
A clear and concise description of any alternative solutions or features you've considered.
22+
### Describe the Solution You'd Like
23+
A clear and concise description of the feature or API change you want.
24+
Be specific about input/outputs if this involves an API change.
2125

22-
**Additional context**
23-
Add any other context or screenshots about the feature request here.
26+
### Impact on your work
27+
How does this feature impact your work and what are you trying to achieve?
28+
If this is critical for you, tell us if there is a timeline by when you need
29+
this feature.
30+
31+
### Willingness to contribute
32+
Are you interested in implementing this feature yourself or submitting a PR?
33+
(Yes/No)
34+
35+
---
36+
37+
## 🟡 Recommended Information
38+
39+
### Describe Alternatives You've Considered
40+
A clear and concise description of any alternative solutions or workarounds
41+
you've considered and why they didn't work for you.
42+
43+
### Proposed API / Implementation
44+
If you have ideas on how this should look in code, please share a
45+
pseudo-code example.
46+
47+
### Additional Context
48+
Add any other context or screenshots about the feature request here.

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
### ⚠ BREAKING CHANGES
66

77
* Breaking: Use OpenTelemetry for BigQuery plugin tracing, replacing custom `ContextVar` implementation ([ab89d12](https://github.com/google/adk-python/commit/ab89d1283430041afb303834749869e9ee331721))
8-
* Add support to automatically create a session if one does not exist ([8e69a58](https://github.com/google/adk-python/commit/8e69a58df4eadeccbb100b7264bb518a46b61fd7))
98

109
### Features
1110

1211
* **[Core]**
12+
* Add support to automatically create a session if one does not exist ([8e69a58](https://github.com/google/adk-python/commit/8e69a58df4eadeccbb100b7264bb518a46b61fd7))
1313
* Remove `@experimental` decorator from `AgentEngineSandboxCodeExecutor` ([135f763](https://github.com/google/adk-python/commit/135f7633253f6a415302142abc3579b664601d5b))
1414
* Add `--disable_features` CLI option to override default feature enable state ([53b67ce](https://github.com/google/adk-python/commit/53b67ce6340f3f3f8c3d732f9f7811e445c76359))
1515
* Add `otel_to_cloud` flag to `adk deploy agent_engine` command ([21f63f6](https://github.com/google/adk-python/commit/21f63f66ee424501d9a70806277463ef718ae843))

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ part before or alongside your code PR.
188188
pytest ./tests/unittests
189189
```
190190

191+
**Alternatively**, use the included `unittests.sh` script which handles
192+
environment setup and restoration automatically:
193+
194+
```shell
195+
./scripts/unittests.sh
196+
```
197+
198+
This script will:
199+
- Set up the test environment with minimal dependencies (`test`, `eval`, `a2a`)
200+
- Run the unit tests
201+
- Restore the full development environment (`--all-extras`)
202+
191203
6. **Auto-format the code:**
192204

193205
**NOTE**: We use `isort` and `pyink` for styles. Use the included

contributing/samples/adk_documentation/adk_release_analyzer/agent.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ def get_release_context(tool_context: ToolContext) -> dict[str, Any]:
272272
273273
3. Call `get_changed_files_summary` to get the list of changed files WITHOUT
274274
the full patches (to save context space).
275+
- **IMPORTANT**: Pass `local_repo_path="{LOCAL_REPOS_DIR_PATH}/{CODE_REPO}"`
276+
to use local git and avoid GitHub API's 300-file limit.
275277
276278
4. Filter and organize the files:
277279
- **INCLUDE** only files in `src/google/adk/` directory

contributing/samples/adk_documentation/tools.py

Lines changed: 150 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -600,23 +600,37 @@ def get_file_diff_for_release(
600600

601601

602602
def get_changed_files_summary(
603-
repo_owner: str, repo_name: str, start_tag: str, end_tag: str
603+
repo_owner: str,
604+
repo_name: str,
605+
start_tag: str,
606+
end_tag: str,
607+
local_repo_path: Optional[str] = None,
604608
) -> Dict[str, Any]:
605609
"""Gets a summary of changed files between two releases without patches.
606610
607-
This is a lighter-weight version of get_changed_files_between_releases
608-
that only returns file paths and metadata, without the actual diff content.
609-
Use this for planning which files to analyze.
611+
This function uses local git commands when local_repo_path is provided,
612+
which avoids the GitHub API's 300-file limit for large comparisons.
613+
Falls back to GitHub API if local_repo_path is not provided or invalid.
610614
611615
Args:
612616
repo_owner: The name of the repository owner.
613617
repo_name: The name of the repository.
614618
start_tag: The older tag (base) for the comparison.
615619
end_tag: The newer tag (head) for the comparison.
620+
local_repo_path: Optional absolute path to local git repo. If provided
621+
and valid, uses git diff instead of GitHub API to get complete
622+
file list (avoids 300-file limit).
616623
617624
Returns:
618625
A dictionary containing the status and a summary of changed files.
619626
"""
627+
# Use local git if valid path is provided (avoids GitHub API 300-file limit)
628+
if local_repo_path and os.path.isdir(os.path.join(local_repo_path, ".git")):
629+
return _get_changed_files_from_local_git(
630+
local_repo_path, start_tag, end_tag, repo_owner, repo_name
631+
)
632+
633+
# Fall back to GitHub API (limited to 300 files)
620634
url = f"{GITHUB_BASE_URL}/repos/{repo_owner}/{repo_name}/compare/{start_tag}...{end_tag}"
621635

622636
try:
@@ -654,8 +668,140 @@ def get_changed_files_summary(
654668
f"https://github.com/{repo_owner}/{repo_name}"
655669
f"/compare/{start_tag}...{end_tag}"
656670
),
671+
"note": (
672+
(
673+
"Using GitHub API which is limited to 300 files. "
674+
"Provide local_repo_path to get complete file list."
675+
)
676+
if len(formatted_files) >= 300
677+
else None
678+
),
657679
}
658680
except requests.exceptions.HTTPError as e:
659681
return error_response(f"HTTP Error: {e}")
660682
except requests.exceptions.RequestException as e:
661683
return error_response(f"Request Error: {e}")
684+
685+
686+
def _get_changed_files_from_local_git(
687+
local_repo_path: str,
688+
start_tag: str,
689+
end_tag: str,
690+
repo_owner: str,
691+
repo_name: str,
692+
) -> Dict[str, Any]:
693+
"""Gets changed files using local git commands (no file limit).
694+
695+
Args:
696+
local_repo_path: Path to local git repository.
697+
start_tag: The older tag (base) for the comparison.
698+
end_tag: The newer tag (head) for the comparison.
699+
repo_owner: Repository owner for compare URL.
700+
repo_name: Repository name for compare URL.
701+
702+
Returns:
703+
A dictionary containing the status and a summary of changed files.
704+
"""
705+
try:
706+
# Fetch tags to ensure we have them
707+
subprocess.run(
708+
["git", "fetch", "--tags"],
709+
cwd=local_repo_path,
710+
capture_output=True,
711+
text=True,
712+
check=False,
713+
)
714+
715+
# Get list of changed files with their status
716+
diff_result = subprocess.run(
717+
["git", "diff", "--name-status", f"{start_tag}...{end_tag}"],
718+
cwd=local_repo_path,
719+
capture_output=True,
720+
text=True,
721+
check=True,
722+
)
723+
724+
# Get numstat for additions/deletions
725+
numstat_result = subprocess.run(
726+
["git", "diff", "--numstat", f"{start_tag}...{end_tag}"],
727+
cwd=local_repo_path,
728+
capture_output=True,
729+
text=True,
730+
check=True,
731+
)
732+
733+
# Parse numstat output (additions, deletions, filename)
734+
file_stats: Dict[str, Dict[str, int]] = {}
735+
for line in numstat_result.stdout.strip().split("\n"):
736+
if not line:
737+
continue
738+
parts = line.split("\t")
739+
if len(parts) >= 3:
740+
additions = int(parts[0]) if parts[0] != "-" else 0
741+
deletions = int(parts[1]) if parts[1] != "-" else 0
742+
filename = parts[2]
743+
file_stats[filename] = {
744+
"additions": additions,
745+
"deletions": deletions,
746+
"changes": additions + deletions,
747+
}
748+
749+
# Parse name-status output and combine with numstat
750+
status_map = {
751+
"A": "added",
752+
"D": "removed",
753+
"M": "modified",
754+
"R": "renamed",
755+
"C": "copied",
756+
}
757+
758+
files_by_dir: Dict[str, List[Dict[str, Any]]] = {}
759+
formatted_files = []
760+
761+
for line in diff_result.stdout.strip().split("\n"):
762+
if not line:
763+
continue
764+
parts = line.split("\t")
765+
if len(parts) >= 2:
766+
status_code = parts[0][0] # First char is the status
767+
filename = parts[-1] # Last part is filename (handles renames)
768+
769+
stats = file_stats.get(
770+
filename,
771+
{
772+
"additions": 0,
773+
"deletions": 0,
774+
"changes": 0,
775+
},
776+
)
777+
778+
file_info = {
779+
"relative_path": filename,
780+
"status": status_map.get(status_code, "modified"),
781+
"additions": stats["additions"],
782+
"deletions": stats["deletions"],
783+
"changes": stats["changes"],
784+
}
785+
formatted_files.append(file_info)
786+
787+
# Group by top-level directory
788+
dir_parts = filename.split("/")
789+
top_dir = dir_parts[0] if dir_parts else "root"
790+
if top_dir not in files_by_dir:
791+
files_by_dir[top_dir] = []
792+
files_by_dir[top_dir].append(file_info)
793+
794+
return {
795+
"status": "success",
796+
"total_files": len(formatted_files),
797+
"files": formatted_files,
798+
"files_by_directory": files_by_dir,
799+
"compare_url": (
800+
f"https://github.com/{repo_owner}/{repo_name}"
801+
f"/compare/{start_tag}...{end_tag}"
802+
),
803+
}
804+
except subprocess.CalledProcessError as e:
805+
return error_response(f"Git command failed: {e.stderr}")
806+
except (OSError, ValueError) as e:
807+
return error_response(f"Error getting changed files: {e}")

contributing/samples/data_agent/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ questions in the same session, and the agent will maintain context.
3737
* `get_data_agent_info`: Retrieves details about a specific Data Agent given
3838
its full resource name.
3939
* `ask_data_agent`: Chats with a specific Data Agent using natural language.
40-
This tool maintains conversation state: if you ask multiple
41-
questions to the same agent in one session, it will use the same
42-
conversation, allowing for follow-ups. If you switch agents, a new
43-
conversation will be started for the new agent.
4440

4541
## How to Run
4642

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ test = [
127127
"llama-index-readers-file>=0.4.0", # For retrieval tests
128128
"openai>=1.100.2", # For LiteLLM
129129
"opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0",
130+
"pypika>=0.50.0", # For crewai->chromadb dependency
130131
"pytest-asyncio>=0.25.0",
131132
"pytest-mock>=3.14.0",
132133
"pytest-xdist>=3.6.1",
@@ -158,6 +159,7 @@ extensions = [
158159
"llama-index-readers-file>=0.4.0", # For retrieval using LlamaIndex.
159160
"llama-index-embeddings-google-genai>=0.3.0", # For files retrieval using LlamaIndex.
160161
"lxml>=5.3.0", # For load_web_page tool.
162+
"pypika>=0.50.0", # For crewai->chromadb dependency
161163
"toolbox-adk>=0.5.7, <0.6.0", # For tools.toolbox_toolset.ToolboxToolset
162164
]
163165

0 commit comments

Comments
 (0)