Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
a2a

Check warning on line 1 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
A2A

Check warning on line 2 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
A2AFastAPI

Check warning on line 3 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
AAgent
Expand Down Expand Up @@ -28,7 +28,7 @@
AUser
autouse
backticks
base64url

Check warning on line 31 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
buf
bufbuild
cla
Expand All @@ -46,7 +46,7 @@
drivername
DSNs
dunders
ES256

Check warning on line 49 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
euo
EUR
evt
Expand All @@ -62,8 +62,8 @@
gowebpki
GVsb
hazmat
HS256

Check warning on line 65 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
HS384

Check warning on line 66 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
ietf
importlib
initdb
Expand Down Expand Up @@ -106,10 +106,10 @@
Oneof
OpenAPI
openapiv
openapiv2

Check warning on line 109 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
opensource
otherurl
pb2

Check warning on line 112 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
podman
Podman
poolclass
Expand All @@ -132,13 +132,14 @@
respx
resub
rmi
RS256

Check warning on line 135 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
RUF
Rundgren
SECP256R1
SFIXED
SLF
socio
sourced
sse
starlette
Starlette
Expand Down
203 changes: 37 additions & 166 deletions itk/run_itk.sh
Original file line number Diff line number Diff line change
@@ -1,174 +1,45 @@
#!/bin/bash
set -ex

# Set default log level
export ITK_LOG_LEVEL="${ITK_LOG_LEVEL:-INFO}"

# Initialize default exit code
RESULT=1

# Cleanup function to be called on exit
cleanup() {
set +x
echo "Cleaning up artifacts..."
docker stop itk-service > /dev/null 2>&1 || true
docker rm itk-service > /dev/null 2>&1 || true
docker rmi itk_service > /dev/null 2>&1 || true
rm -rf a2a-itk > /dev/null 2>&1 || true
rm -rf pyproto > /dev/null 2>&1 || true
rm -f instruction.proto > /dev/null 2>&1 || true
echo "Done. Final exit code: $RESULT"
# ITK harness for a2a-python — a thin shim over a2a-itk's shared driver.
#
# Everything that used to live here (clone, image build, container start,
# readiness poll, POST /run, result reporting, nightly metrics) is now in
# a2a-itk/scripts/run_itk_shared.sh, which all five SDK repos share. Only the
# genuinely python-specific part stays: generating the proto stubs.
#
# Scenarios come from the shared role-based set in a2a-itk rather than a
# scenarios.json in this repo — see a2a-itk/scenarios/traversal/.
set -e
cd "$(dirname "${BASH_SOURCE[0]}")"

ITK_SDK_NAME=python
ITK_SCENARIO_SET=shared

itk_generate_protos() {
mkdir -p pyproto
touch pyproto/__init__.py
uv run --with grpcio-tools python -m grpc_tools.protoc \
-I. \
--python_out=pyproto \
--grpc_python_out=pyproto \
instruction.proto
# Generated code imports its sibling as a top-level module; make it relative
# so `pyproto` works as a package.
sed -i 's/^import instruction_pb2 as instruction__pb2/from . import instruction_pb2 as instruction__pb2/' \
pyproto/instruction_pb2_grpc.py
}

# Register cleanup function to run on script exit
trap cleanup EXIT
itk_extra_cleanup() {
rm -rf pyproto
}

# 1. Pull a2a-itk and checkout revision
# --- bootstrap -------------------------------------------------------------
# The shared driver lives in a2a-itk, so the checkout has to exist before it
# can be sourced. CI has already placed it here via actions/checkout; locally
# we clone it from a2aproject/a2a-itk.
: "${A2A_ITK_REVISION:?A2A_ITK_REVISION environment variable must be set}"

if [ ! -d "a2a-itk" ]; then
if [ ! -d a2a-itk ]; then
git clone https://github.com/a2aproject/a2a-itk.git a2a-itk
git -C a2a-itk checkout "$A2A_ITK_REVISION"
fi
cd a2a-itk
git fetch origin
git checkout "$A2A_ITK_REVISION"

# Only pull if it's a branch (not a detached HEAD)
if git symbolic-ref -q HEAD > /dev/null; then
git pull origin "$A2A_ITK_REVISION"
fi
cd ..

# 2. Copy instruction.proto from a2a-itk
cp a2a-itk/protos/instruction.proto ./instruction.proto

# 3. Build pyproto library
mkdir -p pyproto
touch pyproto/__init__.py
uv run --with grpcio-tools python -m grpc_tools.protoc \
-I. \
--python_out=pyproto \
--grpc_python_out=pyproto \
instruction.proto

# Fix imports in generated file
sed -i 's/^import instruction_pb2 as instruction__pb2/from . import instruction_pb2 as instruction__pb2/' pyproto/instruction_pb2_grpc.py

# 4. Build jit itk_service docker image from root of a2a-itk (skipped in CI
# where the workflow builds via docker/build-push-action for GHA caching).
if [ "${ITK_SKIP_BUILD:-0}" != "1" ]; then
docker build -t itk_service a2a-itk
fi

# 5. Start docker service
# Mounting a2a-python as repo and itk as current agent
A2A_PYTHON_ROOT=$(cd .. && pwd)
ITK_DIR=$(pwd)

# Stop existing container if any
docker rm -f itk-service || true

# Create logs directory if debug
if [ "${ITK_LOG_LEVEL^^}" = "DEBUG" ]; then
mkdir -p "$ITK_DIR/logs"
fi

DOCKER_MOUNT_LOGS=""
if [ "${ITK_LOG_LEVEL^^}" = "DEBUG" ]; then
DOCKER_MOUNT_LOGS="-v $ITK_DIR/logs:/app/logs"
fi

mkdir -p "$HOME/.cache/a2a-itk-launcher"

docker run -d --name itk-service \
-v "$A2A_PYTHON_ROOT:/app/agents/repo" \
-v "$ITK_DIR:/app/agents/repo/itk" \
-v "$HOME/.cache/a2a-itk-launcher:/root/.cache/a2a-itk" \
$DOCKER_MOUNT_LOGS \
-e ITK_LOG_LEVEL="$ITK_LOG_LEVEL" \
-e ITK_ENTRYPOINT="${ITK_ENTRYPOINT:-itk_service_v2.py}" \
-e ITK_READINESS_TIMEOUT="${ITK_READINESS_TIMEOUT:-180}" \
-e ITK_MAX_WORKERS="${ITK_MAX_WORKERS:-2}" \
-p 8000:8000 \
itk_service

# 5.1. Fix dubious ownership for git (needed for uv-dynamic-versioning)
docker exec -u root itk-service git config --system --add safe.directory /app/agents/repo
docker exec -u root itk-service git config --system --add safe.directory /app/agents/repo/itk
docker exec -u root itk-service git config --system core.multiPackIndex false
# Launcher's peer checkouts under /root/.cache/a2a-itk are host-owned; trust
# only repos under the launcher cache dir so container-side git accepts them.
docker exec -u root itk-service bash -lc 'while IFS= read -r -d "" d; do git config --system --add safe.directory "${d%/.git}"; done < <(find /root/.cache/a2a-itk -type d -name .git -print0)'

# 6. Verify service is up and send post request
MAX_RETRIES=30
echo "Waiting for ITK service to start on 127.0.0.1:8000..."
set +e
for i in $(seq 1 $MAX_RETRIES); do
if curl -s http://127.0.0.1:8000/ > /dev/null; then
echo "Service is up!"
break
fi
echo "Still waiting... ($i/$MAX_RETRIES)"
sleep 2
done

# If we reached the end of the loop without success
if ! curl -s http://127.0.0.1:8000/ > /dev/null; then
echo "Error: ITK service failed to start on port 8000"
docker logs itk-service
exit 1
fi

SCENARIO_FILE="scenarios.json"
if [ "${ITK_NIGHTLY_RUN^^}" = "TRUE" ]; then
SCENARIO_FILE="scenarios_full.json"
fi

echo "ITK Service is up! Sending compatibility test request using $SCENARIO_FILE..."
RESPONSE=$(curl -s -X POST http://127.0.0.1:8000/run \
-H "Content-Type: application/json" \
-d "@$SCENARIO_FILE")

if [ "${ITK_NIGHTLY_RUN^^}" = "TRUE" ]; then
echo "Nightly run detected. Saving raw results and running process_results.py..."
echo "$RESPONSE" > raw_results.json
python3 a2a-itk/scripts/process_results.py \
--history_output_file itk_python.json \
--history_url https://github.com/a2aproject/a2a-python/releases/download/nightly-metrics/itk_python.json
RESULT=$?
else
echo "--------------------------------------------------------"
echo "ITK TEST RESULTS:"
echo "--------------------------------------------------------"
echo "$RESPONSE" | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
all_passed = data.get('all_passed', False)
results = data.get('results', {})
for test, passed in results.items():
status = 'PASSED' if passed else 'FAILED'
print(f'{test}: {status}')
print('--------------------------------------------------------')
print(f'OVERALL STATUS: {\"PASSED\" if all_passed else \"FAILED\"}')
if not all_passed:
sys.exit(1)
except Exception as e:
print(f'Error parsing results: {e}')
print(f'Raw response: {data if \"data\" in locals() else \"no data\"}')
sys.exit(1)
"
RESULT=$?
fi
set -e

if [ $RESULT -ne 0 ]; then
echo "Tests failed. Container logs:"
docker logs itk-service
fi
echo "--------------------------------------------------------"

# Final exit result will be captured by trap cleanup
exit $RESULT

source a2a-itk/scripts/run_itk_shared.sh
64 changes: 0 additions & 64 deletions itk/scenarios.json

This file was deleted.

Loading
Loading