Skip to content

Commit a5234fc

Browse files
committed
Merge branch 'fix-bug#367-client_hangs' of https://github.com/meoow113/a2a-python into fix-bug#367-client_hangs
2 parents 7119604 + e13b5d8 commit a5234fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1654
-611
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ agentic
99
AGrpc
1010
aio
1111
aiomysql
12+
amannn
1213
aproject
1314
ARequest
1415
ARun
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: "Conventional Commits"
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
- edited
8+
- synchronize
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
main:
15+
permissions:
16+
pull-requests: read
17+
statuses: write
18+
name: Validate PR Title
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: semantic-pull-request
22+
uses: amannn/[email protected]
23+
env:
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
with:
26+
validateSingleCommit: false

.github/workflows/unit-tests.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,21 @@ jobs:
4040
steps:
4141
- name: Checkout code
4242
uses: actions/checkout@v4
43-
- name: Set up Python ${{ matrix.python-version }}
44-
uses: actions/setup-python@v5
45-
with:
46-
python-version: ${{ matrix.python-version }}
4743
- name: Set up test environment variables
4844
run: |
4945
echo "POSTGRES_TEST_DSN=postgresql+asyncpg://a2a:a2a_password@localhost:5432/a2a_test" >> $GITHUB_ENV
5046
echo "MYSQL_TEST_DSN=mysql+aiomysql://a2a:a2a_password@localhost:3306/a2a_test" >> $GITHUB_ENV
5147
52-
- name: Install uv
48+
- name: Install uv for Python ${{ matrix.python-version }}
5349
uses: astral-sh/setup-uv@v6
50+
with:
51+
python-version: ${{ matrix.python-version }}
5452
- name: Add uv to PATH
5553
run: |
5654
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
5755
- name: Install dependencies
5856
run: uv sync --dev --extra sql --extra encryption --extra grpc --extra telemetry
5957
- name: Run tests and check coverage
60-
run: uv run pytest --cov=a2a --cov-report term --cov-fail-under=89
58+
run: uv run pytest --cov=a2a --cov-report term --cov-fail-under=88
6159
- name: Show coverage summary in log
6260
run: uv run coverage report

.ruff.toml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ ignore = [
2929
"ANN002",
3030
"ANN003",
3131
"ANN401",
32+
"TRY003",
33+
"G004",
34+
"TRY201",
35+
"FIX002",
3236
]
3337

3438
select = [
@@ -57,6 +61,20 @@ select = [
5761
"TD", # flake8-todos (check TODO format - Google Style §3.7)
5862
"TCH",# flake8-type-checking (helps manage TYPE_CHECKING blocks and imports)
5963
"PYI",# flake8-pyi (best practices for .pyi stub files, some rules are useful for .py too)
64+
"S", # flake8-bandit (security issues)
65+
"DTZ",# flake8-datetimez (timezone-aware datetimes)
66+
"ERA",# flake8-eradicate (commented-out code)
67+
"Q", # flake8-quotes (quote style consistency)
68+
"RSE",# flake8-raise (modern raise statements)
69+
"TRY",# tryceratops (exception handling best practices)
70+
"PERF",# perflint (performance anti-patterns)
71+
"BLE",
72+
"T10",
73+
"ICN",
74+
"G",
75+
"FIX",
76+
"ASYNC",
77+
"INP",
6078
]
6179

6280
exclude = [
@@ -104,7 +122,7 @@ ignore-decorators = ["typing.overload", "abc.abstractmethod"]
104122

105123
[lint.flake8-annotations]
106124
mypy-init-return = true
107-
allow-star-arg-any = true
125+
allow-star-arg-any = false
108126

109127
[lint.pep8-naming]
110128
ignore-names = ["test_*", "setUp", "tearDown", "mock_*"]
@@ -139,6 +157,7 @@ inline-quotes = "single"
139157
"types.py" = ["D", "E501"] # Ignore docstring and annotation issues in types.py
140158
"proto_utils.py" = ["D102", "PLR0911"]
141159
"helpers.py" = ["ANN001", "ANN201", "ANN202"]
160+
"scripts/*.py" = ["INP001"]
142161

143162
[format]
144163
exclude = [

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## [0.3.1](https://github.com/a2aproject/a2a-python/compare/v0.3.0...v0.3.1) (2025-08-13)
4+
5+
6+
### Features
7+
8+
* Add agent card as a route in rest adapter ([ba93053](https://github.com/a2aproject/a2a-python/commit/ba93053850a767a8959bc634883008fcc1366e09))
9+
10+
11+
### Bug Fixes
12+
13+
* gracefully handle task exceptions in event consumer ([#383](https://github.com/a2aproject/a2a-python/issues/383)) ([2508a9b](https://github.com/a2aproject/a2a-python/commit/2508a9b8ec1a1bfdc61e9012b7d68b33082b3981))
14+
* openapi working in sub-app ([#324](https://github.com/a2aproject/a2a-python/issues/324)) ([dec4b48](https://github.com/a2aproject/a2a-python/commit/dec4b487514db6cbb25f0c6fa7e1275a1ab0ba71))
15+
* Pass `message_length` param in `get_task()` ([#384](https://github.com/a2aproject/a2a-python/issues/384)) ([b6796b9](https://github.com/a2aproject/a2a-python/commit/b6796b9e1432ef8499eff454f869edf4427fd704))
16+
* relax protobuf dependency version requirement ([#381](https://github.com/a2aproject/a2a-python/issues/381)) ([0f55f55](https://github.com/a2aproject/a2a-python/commit/0f55f554ba9f6bf53fa3d9a91f66939f36e1ef2e))
17+
* Use HasField for simple message retrieval for grpc transport ([#380](https://github.com/a2aproject/a2a-python/issues/380)) ([3032aa6](https://github.com/a2aproject/a2a-python/commit/3032aa660f6f3b72dc7dd8b49b0e2f4d432c7a22))
18+
319
## [0.3.0](https://github.com/a2aproject/a2a-python/compare/v0.2.16...v0.3.0) (2025-07-31)
420

521

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ When you're working within a uv project or a virtual environment managed by uv,
3333
uv add a2a-sdk
3434
```
3535

36+
To include the optional HTTP server components (FastAPI, Starlette), install the `http-server` extra:
37+
38+
```bash
39+
uv add a2a-sdk[http-server]
40+
```
41+
3642
To install with gRPC support:
3743

3844
```bash
@@ -69,6 +75,12 @@ If you prefer to use pip, the standard Python package installer, you can install
6975
pip install a2a-sdk
7076
```
7177

78+
To include the optional HTTP server components (FastAPI, Starlette), install the `http-server` extra:
79+
80+
```bash
81+
pip install a2a-sdk[http-server]
82+
```
83+
7284
To install with gRPC support:
7385

7486
```bash

pyproject.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@ authors = [{ name = "Google LLC", email = "[email protected]" }]
88
requires-python = ">=3.10"
99
keywords = ["A2A", "A2A SDK", "A2A Protocol", "Agent2Agent", "Agent 2 Agent"]
1010
dependencies = [
11-
"fastapi>=0.95.0",
1211
"httpx>=0.28.1",
1312
"httpx-sse>=0.4.0",
1413
"pydantic>=2.11.3",
15-
"sse-starlette",
16-
"starlette",
1714
"protobuf>=5.29.5",
1815
"google-api-core>=1.26.0",
1916
]
@@ -32,6 +29,7 @@ classifiers = [
3229
]
3330

3431
[project.optional-dependencies]
32+
http-server = ["fastapi>=0.115.2", "sse-starlette", "starlette"]
3533
postgresql = ["sqlalchemy[asyncio,postgresql-asyncpg]>=2.0.0"]
3634
mysql = ["sqlalchemy[asyncio,aiomysql]>=2.0.0"]
3735
sqlite = ["sqlalchemy[asyncio,aiosqlite]>=2.0.0"]
@@ -84,11 +82,14 @@ dev = [
8482
"pytest-cov>=6.1.1",
8583
"pytest-mock>=3.14.0",
8684
"respx>=0.20.2",
87-
"ruff>=0.11.6",
85+
"ruff>=0.12.8",
8886
"uv-dynamic-versioning>=0.8.2",
8987
"types-protobuf",
9088
"types-requests",
9189
"pre-commit",
90+
"fastapi>=0.115.2",
91+
"sse-starlette",
92+
"starlette",
9293
"pyupgrade",
9394
"autoflake",
9495
"no_implicit_optional",

scripts/format.sh

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,23 @@ FORMAT_ALL=false
88
RUFF_UNSAFE_FIXES_FLAG=""
99

1010
# Process command-line arguments
11-
# We use a while loop with shift to process each argument
1211
while [[ "$#" -gt 0 ]]; do
1312
case "$1" in
14-
--all)
15-
FORMAT_ALL=true
16-
echo "Detected --all flag: Formatting all Python files."
17-
shift # Consume the argument
18-
;;
19-
--unsafe-fixes)
20-
RUFF_UNSAFE_FIXES_FLAG="--unsafe-fixes"
21-
echo "Detected --unsafe-fixes flag: Ruff will run with unsafe fixes."
22-
shift # Consume the argument
23-
;;
24-
*)
25-
# Handle unknown arguments or just ignore them if we only care about specific ones
26-
echo "Warning: Unknown argument '$1'. Ignoring."
27-
shift # Consume the argument
28-
;;
13+
--all)
14+
FORMAT_ALL=true
15+
echo "Detected --all flag: Formatting all tracked Python files."
16+
shift # Consume the argument
17+
;;
18+
--unsafe-fixes)
19+
RUFF_UNSAFE_FIXES_FLAG="--unsafe-fixes"
20+
echo "Detected --unsafe-fixes flag: Ruff will run with unsafe fixes."
21+
shift # Consume the argument
22+
;;
23+
*)
24+
# Handle unknown arguments or just ignore them
25+
echo "Warning: Unknown argument '$1'. Ignoring."
26+
shift # Consume the argument
27+
;;
2928
esac
3029
done
3130

@@ -39,47 +38,52 @@ fi
3938
CHANGED_FILES=""
4039

4140
if $FORMAT_ALL; then
42-
echo "Formatting all Python files in the repository."
43-
# Find all Python files, excluding grpc generated files as per original logic.
44-
# `sort -u` ensures unique files and consistent ordering for display/xargs.
45-
CHANGED_FILES=$(find . -name '*.py' -not -path './src/a2a/grpc/*' | sort -u)
46-
47-
if [ -z "$CHANGED_FILES" ]; then
48-
echo "No Python files found to format."
49-
exit 0
50-
fi
41+
echo "Finding all tracked Python files in the repository..."
42+
CHANGED_FILES=$(git ls-files -- '*.py' ':!src/a2a/grpc/*')
5143
else
52-
echo "No '--all' flag found. Formatting changed Python files based on git diff."
44+
echo "Finding changed Python files based on git diff..."
5345
TARGET_BRANCH="origin/${GITHUB_BASE_REF:-main}"
5446
git fetch origin "${GITHUB_BASE_REF:-main}" --depth=1
5547

5648
MERGE_BASE=$(git merge-base HEAD "$TARGET_BRANCH")
5749

58-
# Get python files changed in this PR, excluding grpc generated files
50+
# Get python files changed in this PR, excluding grpc generated files.
5951
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "$MERGE_BASE" HEAD -- '*.py' ':!src/a2a/grpc/*')
60-
61-
if [ -z "$CHANGED_FILES" ]; then
62-
echo "No changed Python files to format."
63-
exit 0
64-
fi
6552
fi
6653

67-
echo "Files to be formatted:"
68-
echo "$CHANGED_FILES"
54+
# Exit if no files were found
55+
if [ -z "$CHANGED_FILES" ]; then
56+
echo "No changed or tracked Python files to format."
57+
exit 0
58+
fi
6959

70-
# Helper function to run formatters with the list of files.
71-
# The list of files is passed to xargs via stdin.
60+
# --- Helper Function ---
61+
# Runs a command on a list of files passed via stdin.
62+
# $1: A string containing the list of files (space-separated).
63+
# $2...: The command and its arguments to run.
7264
run_formatter() {
73-
echo "$CHANGED_FILES" | xargs -r "$@"
65+
local files_to_format="$1"
66+
shift # Remove the file list from the arguments
67+
if [ -n "$files_to_format" ]; then
68+
echo "$files_to_format" | xargs -r "$@"
69+
fi
7470
}
7571

76-
echo "Running pyupgrade..."
77-
run_formatter pyupgrade --exit-zero-even-if-changed --py310-plus
78-
echo "Running autoflake..."
79-
run_formatter autoflake -i -r --remove-all-unused-imports
80-
echo "Running ruff check (fix-only)..."
81-
run_formatter ruff check --fix $RUFF_UNSAFE_FIXES_FLAG
82-
echo "Running ruff format..."
83-
run_formatter ruff format
72+
# --- Python File Formatting ---
73+
if [ -n "$CHANGED_FILES" ]; then
74+
echo "--- Formatting Python Files ---"
75+
echo "Files to be formatted:"
76+
echo "$CHANGED_FILES"
77+
78+
echo "Running autoflake..."
79+
run_formatter "$CHANGED_FILES" autoflake -i -r --remove-all-unused-imports
80+
echo "Running ruff check (fix-only)..."
81+
run_formatter "$CHANGED_FILES" ruff check --fix-only $RUFF_UNSAFE_FIXES_FLAG
82+
echo "Running ruff format..."
83+
run_formatter "$CHANGED_FILES" ruff format
84+
echo "Python formatting complete."
85+
else
86+
echo "No Python files to format."
87+
fi
8488

85-
echo "Formatting complete."
89+
echo "All formatting tasks are complete."

scripts/grpc_gen_post_processor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def process_generated_code(src_folder: str = 'src/a2a/grpc') -> None:
4747
else:
4848
print('No changes needed')
4949

50-
except Exception as e:
50+
except Exception as e: # noqa: BLE001
5151
print(f'Error processing file {file}: {e}')
5252
sys.exit(1)
5353

src/a2a/client/transports/grpc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,10 @@ async def get_task(
138138
) -> Task:
139139
"""Retrieves the current state and history of a specific task."""
140140
task = await self.stub.GetTask(
141-
a2a_pb2.GetTaskRequest(name=f'tasks/{request.id}')
141+
a2a_pb2.GetTaskRequest(
142+
name=f'tasks/{request.id}',
143+
history_length=request.history_length,
144+
)
142145
)
143146
return proto_utils.FromProto.task(task)
144147

0 commit comments

Comments
 (0)