Compare commits

..

1 Commits

Author SHA1 Message Date
Claude a5e6f5853c fix(sessions): use UTC consistently in append_event for all DB backends
The append_event method had inconsistent timezone handling: SQLite
converted event.timestamp to UTC before stripping tzinfo, while all
other backends (including PostgreSQL) used datetime.fromtimestamp()
which produces naive datetimes in the server's local timezone.

On non-UTC servers, this caused PostgreSQL to store update_time values
offset by hours from SQLite, leading to incorrect staleness checks.

Now all backends first convert to UTC, then strip tzinfo only for
SQLite and PostgreSQL (which require naive datetimes).

https://claude.ai/code/session_01TNMxZwEdKgsQJvWtJhzQiQ
2026-02-11 07:19:50 +00:00
93 changed files with 245 additions and 2053 deletions
-3
View File
@@ -1,3 +0,0 @@
{
".": "1.24.1"
}
-24
View File
@@ -1,24 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"packages": {
".": {
"release-type": "python",
"package-name": "google-adk",
"include-component-in-tag": false,
"skip-github-release": true,
"changelog-path": "CHANGELOG.md",
"changelog-sections": [
{"type": "feat", "section": "Features"},
{"type": "fix", "section": "Bug Fixes"},
{"type": "perf", "section": "Performance Improvements"},
{"type": "refactor", "section": "Code Refactoring"},
{"type": "docs", "section": "Documentation"},
{"type": "test", "section": "Tests", "hidden": true},
{"type": "build", "section": "Build System", "hidden": true},
{"type": "ci", "section": "CI/CD", "hidden": true},
{"type": "style", "section": "Styles", "hidden": true},
{"type": "chore", "section": "Miscellaneous Chores", "hidden": true}
]
}
}
}
+5
View File
@@ -0,0 +1,5 @@
releaseType: python
handleGHRelease: true
bumpMinorPreMajor: false
extraFiles:
- src/google/adk/version.py
+1
View File
@@ -0,0 +1 @@
enabled: true
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.x'
- name: Install isort
run: |
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.x'
- name: Install pyink
run: |
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- name: Checkout code
-46
View File
@@ -1,46 +0,0 @@
# Cherry-picks a commit from main to the release/candidate branch.
# Use this to include bug fixes in an in-progress release.
name: "Release: Cherry-pick"
on:
workflow_dispatch:
inputs:
commit_sha:
description: 'Commit SHA to cherry-pick'
required: true
type: string
permissions:
contents: write
actions: write
jobs:
cherry-pick:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: release/candidate
fetch-depth: 0
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Cherry-pick commit
run: |
echo "Cherry-picking ${{ inputs.commit_sha }} to release/candidate"
git cherry-pick ${{ inputs.commit_sha }}
- name: Push changes
run: |
git push origin release/candidate
echo "Successfully cherry-picked commit to release/candidate"
- name: Trigger Release Please
env:
GH_TOKEN: ${{ github.token }}
run: |
gh workflow run release-please.yml --repo ${{ github.repository }}
echo "Triggered Release Please workflow"
-46
View File
@@ -1,46 +0,0 @@
# Starts the release process by creating a release/candidate branch.
# Triggers release-please to generate a changelog PR.
name: "Release: Cut"
on:
workflow_dispatch:
inputs:
commit_sha:
description: 'Commit SHA to cut from (leave empty for latest main)'
required: false
type: string
permissions:
contents: write
actions: write
jobs:
cut-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.commit_sha || 'main' }}
- name: Check for existing release/candidate branch
env:
GH_TOKEN: ${{ github.token }}
run: |
if git ls-remote --exit-code --heads origin release/candidate &>/dev/null; then
echo "Error: release/candidate branch already exists"
echo "Please finalize or delete the existing release candidate before starting a new one"
exit 1
fi
- name: Create and push release/candidate branch
run: |
git checkout -b release/candidate
git push origin release/candidate
echo "Created branch: release/candidate"
- name: Trigger Release Please
env:
GH_TOKEN: ${{ github.token }}
run: |
gh workflow run release-please.yml --repo ${{ github.repository }}
echo "Triggered Release Please workflow"
-66
View File
@@ -1,66 +0,0 @@
# Triggers when release-please PR is merged to release/candidate.
# Creates the final release/v{version} branch and deletes the candidate branch.
name: "Release: Finalize"
on:
pull_request:
types: [closed]
branches:
- release/candidate
permissions:
contents: write
pull-requests: write
jobs:
finalize:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Check for release-please PR
id: check
env:
LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
run: |
if echo "$LABELS" | grep -q "autorelease: pending"; then
echo "is_release_pr=true" >> $GITHUB_OUTPUT
else
echo "Not a release-please PR, skipping"
echo "is_release_pr=false" >> $GITHUB_OUTPUT
fi
- uses: actions/checkout@v4
if: steps.check.outputs.is_release_pr == 'true'
with:
ref: release/candidate
- name: Extract version from manifest
if: steps.check.outputs.is_release_pr == 'true'
id: version
run: |
VERSION=$(jq -r '.["."]' .github/.release-please-manifest.json)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
- name: Create release branch
if: steps.check.outputs.is_release_pr == 'true'
run: |
git checkout -b "release/v${{ steps.version.outputs.version }}"
git push origin "release/v${{ steps.version.outputs.version }}"
echo "Created branch: release/v${{ steps.version.outputs.version }}"
- name: Delete release/candidate branch
if: steps.check.outputs.is_release_pr == 'true'
run: |
git push origin --delete release/candidate
echo "Deleted branch: release/candidate"
- name: Update PR label to tagged
if: steps.check.outputs.is_release_pr == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr edit ${{ github.event.pull_request.number }} \
--remove-label "autorelease: pending" \
--add-label "autorelease: tagged"
echo "Updated PR label to autorelease: tagged"
-30
View File
@@ -1,30 +0,0 @@
# Runs release-please to create/update a PR with version bump and changelog.
# Triggered by pushes to release/candidate or manually.
name: "Release: Please"
on:
push:
branches:
- release/candidate
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
release-please:
# Skip if this is a release-please PR merge (handled by Release: Finalize)
if: "!startsWith(github.event.head_commit.message, 'chore(release')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: release/candidate
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.RELEASE_PAT }}
config-file: .github/release-please-config.json
manifest-file: .github/.release-please-manifest.json
target-branch: release/candidate
-59
View File
@@ -1,59 +0,0 @@
# Builds and publishes the package to PyPI from a release branch.
# Creates a merge-back PR to sync release changes to main.
name: "Release: Publish to PyPi"
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Validate branch
run: |
if [[ ! "${{ github.ref_name }}" =~ ^release/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Must run from a release/v* branch (e.g., release/v0.3.0)"
exit 1
fi
- name: Extract version
id: version
run: |
VERSION="${{ github.ref_name }}"
VERSION="${VERSION#release/v}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Publishing version: $VERSION"
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build package
run: uv build
- name: Publish to PyPI
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: uv publish
- name: Create merge-back PR
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
run: |
gh pr create \
--base main \
--head "${{ github.ref_name }}" \
--title "chore: merge release v${{ steps.version.outputs.version }} to main" \
--body "Syncs version bump and CHANGELOG from release v${{ steps.version.outputs.version }} to main."
+3 -2
View File
@@ -187,7 +187,8 @@ uv venv --python "python3.11" ".venv" source .venv/bin/activate
uv sync --all-extras ```
**Minimal setup for testing only (matches CI):** `bash uv sync --extra test`
**Minimal setup for testing only (matches CI):** `bash uv sync --extra test
--extra eval --extra a2a`
**Virtual Environment Usage (Required):** - **Always use** `.venv/bin/python` or
`.venv/bin/pytest` directly - **Or activate** with `source .venv/bin/activate`
@@ -362,7 +363,7 @@ catching issues with the public API.
**Quick start:** Run all tests with: `bash pytest tests/unittests`
**Recommended:** Match CI configuration before submitting PRs: `bash uv sync
--extra test && pytest tests/unittests`
--extra test --extra eval --extra a2a && pytest tests/unittests`
**Additional options:** ```bash
-44
View File
@@ -1,49 +1,5 @@
# Changelog
## [1.25.0](https://github.com/google/adk-python/compare/v1.24.1...v1.25.0) (2026-02-11)
### Features
* **[Core]**
* Add a demo for the simple prompt optimizer for the optimization interface ([0abf4cd](https://github.com/google/adk-python/commit/0abf4cd2c7103a071506c9398455a3bd66fe5da5))
* Add `--auto_create_session` flag to `adk api_server` CLI ([40c15d0](https://github.com/google/adk-python/commit/40c15d059599472b40f48272a464eb3cb7345fc6))
* Add `add_events_to_memory` facade for event-delta ([59e8897](https://github.com/google/adk-python/commit/59e88972ae4f10274444593db0607f40cfcc597e))
* Add post-invocation token-threshold compaction with event retention ([a88e864](https://github.com/google/adk-python/commit/a88e8647558a9b9d0bfdf38d2d8de058e3ba0596))
* Add report generation to `adk conformance test` command ([43c437e](https://github.com/google/adk-python/commit/43c437e38b9109b68a81de886d1901e4d8f87a01))
* **[Models]**
* Add base_url option to Gemini LLM class ([781f605](https://github.com/google/adk-python/commit/781f605a1e5de6d77b69d7e7b9835ec6fc8de4bf))
* **[Tools]**
* Enhance google credentials config to support externally passed access token ([3cf43e3](https://github.com/google/adk-python/commit/3cf43e3842d9987499ea70d6f63d6e1c4d4a07db))
* Update agent simulator by improving prompts and add environment data ([7af1858](https://github.com/google/adk-python/commit/7af1858f46b66fa4471c5ba7943385f2d23d08d3))
* Add a load MCP resource tool ([e25227d](https://github.com/google/adk-python/commit/e25227da5e91a8c1192af709f8e8bb2a471ded92))
* Add SkillToolset to adk ([8d02792](https://github.com/google/adk-python/commit/8d0279251ce4fad6f0c84bd7777eb5a74f7ba07a))
* **[Web]**
* Add `/health` and `/version` endpoints to ADK web server ([25ec2c6](https://github.com/google/adk-python/commit/25ec2c6b614cf8d185ff6dbdac5697a210be68da))
### Bug Fixes
* Use async iteration for VertexAiSessionService.list_sessions pagination ([758d337](https://github.com/google/adk-python/commit/758d337c76d877e3174c35f06551cc9beb1def06))
* Fix event loop closed bug in McpSessionManager ([4aa4751](https://github.com/google/adk-python/commit/4aa475145f196fb35fe97290dd9f928548bc737f))
* Preserve thought_signature in function call conversions for interactions API integration ([2010569](https://github.com/google/adk-python/commit/20105690100d9c2f69c061ac08be5e94c50dc39c))
* Propagate grounding and citation metadata in streaming responses ([e6da417](https://github.com/google/adk-python/commit/e6da4172924ecc36ffc2535199c450a2a51c7bcc))
* Add endpoints to get/list artifact version metadata ([e0b9712](https://github.com/google/adk-python/commit/e0b9712a492bf84ac17679095b333642a79b8ee6))
* Support escaped curly braces in instruction templates ([7c7d25a](https://github.com/google/adk-python/commit/7c7d25a4a6e4389e23037e70b8efdcd5341f44ea))
* Strip timezone for PostgreSQL timestamps in DatabaseSessionService ([19b6076](https://github.com/google/adk-python/commit/19b607684f15ce2b6ffd60382211ba5600705743))
* Prompt token may be None in streaming mode ([32ee07d](https://github.com/google/adk-python/commit/32ee07df01f10dbee0e98ca9d412440a7fe9163d))
* Pass invocation_id from `/run` endpoint to `Runner.run_async` ([d2dba27](https://github.com/google/adk-python/commit/d2dba27134f833e5d929fdf363ada9364cc852f9))
* Conditionally preserve function call IDs in LLM requests ([663cb75](https://github.com/google/adk-python/commit/663cb75b3288d8d0649412e1009329502b21cbbc))
* Migrate VertexAiMemoryBankService to use the async Vertex AI client ([64a44c2](https://github.com/google/adk-python/commit/64a44c28974de77cf8934f9c3d1bc03691b90e7b))
* Handle list values in Gemini schema sanitization ([fd8a9e3](https://github.com/google/adk-python/commit/fd8a9e3962cca4f422beb7316cbe732edf726d51))
* Used logger to log instead of print in MCP ([6bc70a6](https://github.com/google/adk-python/commit/6bc70a6bab79b679a4b18ad146b3450fb9014475))
### Improvements
* Replace check of instance for LlmAgent with hasAttribute check ([7110336](https://github.com/google/adk-python/commit/7110336788662abb8c9bbbb0a53a50cc09130d5e))
* Log exception details before re-raising in MCP session execution ([de79bf1](https://github.com/google/adk-python/commit/de79bf12b564a4eefc7e6a2568dbe0f08bb6efeb))
## [1.24.1](https://github.com/google/adk-python/compare/v1.24.0...v1.24.1) (2026-02-06)
### Bug Fixes
+3 -3
View File
@@ -180,11 +180,11 @@ part before or alongside your code PR.
pytest ./tests/unittests
```
NOTE: for accurate repro of test failure, only include `test` as extra
dependencies.
NOTE: for accurate repro of test failure, only include `test`, `eval` and
`a2a` as extra dependencies.
```shell
uv sync --extra test
uv sync --extra test --extra eval --extra a2a
pytest ./tests/unittests
```
-15
View File
@@ -1,18 +1,4 @@
#!/usr/bin/env python3
# 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.
"""
build_llms_txt.py – produce llms.txt and llms-full.txt
– skips ```java``` blocks
@@ -20,7 +6,6 @@ build_llms_txt.py – produce llms.txt and llms-full.txt
– includes Python API reference from HTML files
– includes adk-python repository README
"""
from __future__ import annotations
import argparse
@@ -344,8 +344,7 @@ async def analyze_cache_performance_from_sessions(
print(
" Cache Utilization:"
f" {cached_analysis['cache_utilization_ratio_percent']:.1f}%"
f" ({cached_analysis['requests_with_cache_hits']}/{cached_analysis['total_requests']}"
" requests)"
f" ({cached_analysis['requests_with_cache_hits']}/{cached_analysis['total_requests']} requests)"
)
print(
" Avg Cached Tokens/Request:"
@@ -384,8 +383,7 @@ async def analyze_cache_performance_from_sessions(
print(
" Cache Utilization:"
f" {uncached_analysis['cache_utilization_ratio_percent']:.1f}%"
f" ({uncached_analysis['requests_with_cache_hits']}/{uncached_analysis['total_requests']}"
" requests)"
f" ({uncached_analysis['requests_with_cache_hits']}/{uncached_analysis['total_requests']} requests)"
)
print(
" Avg Cached Tokens/Request:"
@@ -1,6 +1,6 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/google/adk-python/refs/heads/main/src/google/adk/agents/config_schemas/AgentConfig.json
name: search_agent
model: gemini-2.5-flash
model: gemini-2.0-flash
description: 'an agent whose job it is to perform Google search queries and answer questions about the results.'
instruction: You are an agent whose job is to perform Google search queries and answer questions about the results.
tools:
@@ -8,5 +8,3 @@ tools:
generate_content_config:
temperature: 0.1
max_output_tokens: 2000
thinking_config:
include_thoughts: true
@@ -23,7 +23,6 @@ cd tau-bench/
pip install -e . --quiet
```
"""
from __future__ import annotations
from typing import Any
+2 -2
View File
@@ -113,8 +113,8 @@ async def main():
updated_tool_output_data = {
"status": "approved",
"ticketId": ticket_id,
"approver_feedback": (
"Approved by manager at " + str(asyncio.get_event_loop().time())
"approver_feedback": "Approved by manager at " + str(
asyncio.get_event_loop().time()
),
}

Some files were not shown because too many files have changed in this diff Show More