You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8677d5c8dc | |||
| 4d72d31b13 | |||
| 742478fdb7 | |||
| ffcba70686 | |||
| 2f716ada7f | |||
| 17beb32880 | |||
| 7f8dc8927a | |||
| 9a1115c504 | |||
| 913d771d6d | |||
| 58e07cae83 | |||
| 157d9be88d | |||
| 18a541c8fa | |||
| dcea7767c6 | |||
| 2c739ab581 | |||
| 9a207cb832 | |||
| a17ebe6ebd | |||
| 55201cb6a1 | |||
| 0a9625317a | |||
| f9fa7841df | |||
| 5f89a469ec | |||
| 6d174eba30 | |||
| c04adaade1 | |||
| 1ae176ad2f | |||
| 694b71256c | |||
| e1812797ad | |||
| c755cf23c5 | |||
| 94caccc148 | |||
| 476805d5b9 | |||
| e2a81365ec | |||
| 28dfcd2512 | |||
| a6b1baa61b | |||
| e384fa4ad7 | |||
| aafa80bd85 | |||
| 4bda245171 | |||
| 31b81a342d | |||
| fef8778429 | |||
| fe1d5aa439 | |||
| 8201f9aebd | |||
| 1cfc555e70 | |||
| badbcbd7a4 | |||
| 675faefc67 | |||
| a4d432a9e6 | |||
| d1bda9d946 | |||
| a19d617ed8 | |||
| 8ebf229c47 | |||
| b51a1f45fd | |||
| 8932106246 | |||
| 233fd20243 | |||
| d129fd636b | |||
| 131957c531 | |||
| 8e285874da | |||
| cb55970969 | |||
| 40b15ad278 | |||
| dbdeb49090 | |||
| 177980106b | |||
| c5b063f1ff | |||
| 313f1b0913 | |||
| b2fc7740b3 | |||
| 29e4ca9152 | |||
| 4ccda99e8e | |||
| d22920bd7f | |||
| 2ff9b1f639 | |||
| 0a5cf45a75 | |||
| 1551bd4f4d | |||
| bbceb4f2e8 | |||
| b08bdbcd7f | |||
| fc65873d7c | |||
| a7ea374dfb |
@@ -43,11 +43,19 @@ jobs:
|
||||
run: |
|
||||
uv venv .venv
|
||||
source .venv/bin/activate
|
||||
uv sync --extra test --extra eval
|
||||
uv sync --extra test --extra eval --extra a2a
|
||||
|
||||
- name: Run unit tests with pytest
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
pytest tests/unittests \
|
||||
--ignore=tests/unittests/artifacts/test_artifact_service.py \
|
||||
--ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py
|
||||
if [[ "${{ matrix.python-version }}" == "3.9" ]]; then
|
||||
pytest tests/unittests \
|
||||
--ignore=tests/unittests/a2a \
|
||||
--ignore=tests/unittests/tools/mcp_tool \
|
||||
--ignore=tests/unittests/artifacts/test_artifact_service.py \
|
||||
--ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py
|
||||
else
|
||||
pytest tests/unittests \
|
||||
--ignore=tests/unittests/artifacts/test_artifact_service.py \
|
||||
--ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py
|
||||
fi
|
||||
@@ -0,0 +1,43 @@
|
||||
name: ADK Issue Triaging Agent
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
schedule:
|
||||
- cron: '0 */6 * * *' # every 6h
|
||||
|
||||
jobs:
|
||||
agent-triage-issues:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests google-adk
|
||||
|
||||
- name: Run Triaging Script
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.ADK_TRIAGE_AGENT }}
|
||||
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
||||
GOOGLE_GENAI_USE_VERTEXAI: 0
|
||||
OWNER: 'google'
|
||||
REPO: 'adk-python'
|
||||
INTERACTIVE: 0
|
||||
EVENT_NAME: ${{ github.event_name }} # 'issues', 'schedule', etc.
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
ISSUE_TITLE: ${{ github.event.issue.title }}
|
||||
ISSUE_BODY: ${{ github.event.issue.body }}
|
||||
ISSUE_COUNT_TO_PROCESS: '3' # Process 3 issues at a time on schedule
|
||||
run: python contributing/samples/adk_triaging_agent/main.py
|
||||
@@ -1,5 +1,49 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.2](https://github.com/google/adk-python/compare/v1.4.1...v1.4.2) (2025-06-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add type checking to handle different response type of genai API client ([4d72d31](https://github.com/google/adk-python/commit/4d72d31b13f352245baa72b78502206dcbe25406))
|
||||
* This fixes the broken VertexAiSessionService
|
||||
* Allow more credentials types for BigQuery tools ([2f716ad](https://github.com/google/adk-python/commit/2f716ada7fbcf8e03ff5ae16ce26a80ca6fd7bf6))
|
||||
|
||||
## [1.4.1](https://github.com/google/adk-python/compare/v1.3.0...v1.4.1) (2025-06-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add Authenticated Tool (Experimental) ([dcea776](https://github.com/google/adk-python/commit/dcea7767c67c7edfb694304df32dca10b74c9a71))
|
||||
* Add enable_affective_dialog and proactivity to run_config and llm_request ([fe1d5aa](https://github.com/google/adk-python/commit/fe1d5aa439cc56b89d248a52556c0a9b4cbd15e4))
|
||||
* Add import session API in the fast API ([233fd20](https://github.com/google/adk-python/commit/233fd2024346abd7f89a16c444de0cf26da5c1a1))
|
||||
* Add integration tests for litellm with and without turning on add_function_to_prompt ([8e28587](https://github.com/google/adk-python/commit/8e285874da7f5188ea228eb4d7262dbb33b1ae6f))
|
||||
* Allow data_store_specs pass into ADK VAIS built-in tool ([675faef](https://github.com/google/adk-python/commit/675faefc670b5cd41991939fe0fc604df331111a))
|
||||
* Enable MCP Tool Auth (Experimental) ([157d9be](https://github.com/google/adk-python/commit/157d9be88d92f22320604832e5a334a6eb81e4af))
|
||||
* Implement GcsEvalSetResultsManager to handle storage of eval sets on GCS, and refactor eval set results manager ([0a5cf45](https://github.com/google/adk-python/commit/0a5cf45a75aca7b0322136b65ca5504a0c3c7362))
|
||||
* Re-factor some eval sets manager logic, and implement GcsEvalSetsManager to handle storage of eval sets on GCS ([1551bd4](https://github.com/google/adk-python/commit/1551bd4f4d7042fffb497d9308b05f92d45d818f))
|
||||
* Support real time input config ([d22920b](https://github.com/google/adk-python/commit/d22920bd7f827461afd649601326b0c58aea6716))
|
||||
* Support refresh access token automatically for rest_api_tool ([1779801](https://github.com/google/adk-python/commit/177980106b2f7be9a8c0a02f395ff0f85faa0c5a))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix Agent generate config err ([#1305](https://github.com/google/adk-python/issues/1305)) ([badbcbd](https://github.com/google/adk-python/commit/badbcbd7a464e6b323cf3164d2bcd4e27cbc057f))
|
||||
* Fix Agent generate config error ([#1450](https://github.com/google/adk-python/issues/1450)) ([694b712](https://github.com/google/adk-python/commit/694b71256c631d44bb4c4488279ea91d82f43e26))
|
||||
* Fix liteLLM test failures ([fef8778](https://github.com/google/adk-python/commit/fef87784297b806914de307f48c51d83f977298f))
|
||||
* Fix tracing for live ([58e07ca](https://github.com/google/adk-python/commit/58e07cae83048d5213d822be5197a96be9ce2950))
|
||||
* Merge custom http options with adk specific http options in model api request ([4ccda99](https://github.com/google/adk-python/commit/4ccda99e8ec7aa715399b4b83c3f101c299a95e8))
|
||||
* Remove unnecessary double quote on Claude docstring ([bbceb4f](https://github.com/google/adk-python/commit/bbceb4f2e89f720533b99cf356c532024a120dc4))
|
||||
* Set explicit project in the BigQuery client ([6d174eb](https://github.com/google/adk-python/commit/6d174eba305a51fcf2122c0fd481378752d690ef))
|
||||
* Support streaming in litellm + adk and add corresponding integration tests ([aafa80b](https://github.com/google/adk-python/commit/aafa80bd85a49fb1c1a255ac797587cffd3fa567))
|
||||
* Support project-based gemini model path to use google_search_tool ([b2fc774](https://github.com/google/adk-python/commit/b2fc7740b363a4e33ec99c7377f396f5cee40b5a))
|
||||
* Update conversion between Celsius and Fahrenheit ([1ae176a](https://github.com/google/adk-python/commit/1ae176ad2fa2b691714ac979aec21f1cf7d35e45))
|
||||
|
||||
### Chores
|
||||
|
||||
* Set `agent_engine_id` in the VertexAiSessionService constructor, also use the `agent_engine_id` field instead of overriding `app_name` in FastAPI endpoint ([fc65873](https://github.com/google/adk-python/commit/fc65873d7c31be607f6cd6690f142a031631582a))
|
||||
|
||||
|
||||
|
||||
## [1.3.0](https://github.com/google/adk-python/compare/v1.2.1...v1.3.0) (2025-06-11)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# ADK Issue Triaging Assistant
|
||||
|
||||
The ADK Issue Triaging Assistant is a Python-based agent designed to help manage and triage GitHub issues for the `google/adk-python` repository. It uses a large language model to analyze new and unlabelled issues, recommend appropriate labels based on a predefined set of rules, and apply them.
|
||||
|
||||
This agent can be operated in two distinct modes: an interactive mode for local use or as a fully automated GitHub Actions workflow.
|
||||
|
||||
---
|
||||
|
||||
## Interactive Mode
|
||||
|
||||
This mode allows you to run the agent locally to review its recommendations in real-time before any changes are made to your repository's issues.
|
||||
|
||||
### Features
|
||||
* **Web Interface**: The agent's interactive mode can be rendered in a web browser using the ADK's `adk web` command.
|
||||
* **User Approval**: In interactive mode, the agent is instructed to ask for your confirmation before applying a label to a GitHub issue.
|
||||
|
||||
### Running in Interactive Mode
|
||||
To run the agent in interactive mode, first set the required environment variables. Then, execute the following command in your terminal:
|
||||
|
||||
```bash
|
||||
adk web
|
||||
```
|
||||
This will start a local server and provide a URL to access the agent's web interface in your browser.
|
||||
|
||||
---
|
||||
|
||||
## GitHub Workflow Mode
|
||||
|
||||
For automated, hands-off issue triaging, the agent can be integrated directly into your repository's CI/CD pipeline using a GitHub Actions workflow.
|
||||
|
||||
### Workflow Triggers
|
||||
The GitHub workflow is configured to run on specific triggers:
|
||||
|
||||
1. **Issue Events**: The workflow executes automatically whenever a new issue is `opened` or an existing one is `reopened`.
|
||||
|
||||
2. **Scheduled Runs**: The workflow also runs on a recurring schedule (every 6 hours) to process any unlabelled issues that may have been missed.
|
||||
|
||||
### Automated Labeling
|
||||
When running as part of the GitHub workflow, the agent operates non-interactively. It identifies the best label and applies it directly without requiring user approval. This behavior is configured by setting the `INTERACTIVE` environment variable to `0` in the workflow file.
|
||||
|
||||
### Workflow Configuration
|
||||
The workflow is defined in a YAML file (`.github/workflows/triage.yml`). This file contains the steps to check out the code, set up the Python environment, install dependencies, and run the triaging script with the necessary environment variables and secrets.
|
||||
|
||||
---
|
||||
|
||||
## Setup and Configuration
|
||||
|
||||
Whether running in interactive or workflow mode, the agent requires the following setup.
|
||||
|
||||
### Dependencies
|
||||
The agent requires the following Python libraries.
|
||||
|
||||
```bash
|
||||
pip install --upgrade pip
|
||||
pip install google-adk requests
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
The following environment variables are required for the agent to connect to the necessary services.
|
||||
|
||||
* `GITHUB_TOKEN`: **(Required)** A GitHub Personal Access Token with `issues:write` permissions. Needed for both interactive and workflow modes.
|
||||
* `GOOGLE_API_KEY`: **(Required)** Your API key for the Gemini API. Needed for both interactive and workflow modes.
|
||||
* `OWNER`: The GitHub organization or username that owns the repository (e.g., `google`). Needed for both modes.
|
||||
* `REPO`: The name of the GitHub repository (e.g., `adk-python`). Needed for both modes.
|
||||
* `INTERACTIVE`: Controls the agent's interaction mode. For the automated workflow, this is set to `0`. For interactive mode, it should be set to `1` or left unset.
|
||||
|
||||
For local execution in interactive mode, you can place these variables in a `.env` file in the project's root directory. For the GitHub workflow, they should be configured as repository secrets.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Copyright 2025 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.
|
||||
|
||||
from . import agent
|
||||
@@ -13,61 +13,73 @@
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
|
||||
from google.adk import Agent
|
||||
from google.adk.tools.tool_context import ToolContext
|
||||
from google.genai import types
|
||||
import requests
|
||||
|
||||
# Read the PAT from the environment variable
|
||||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") # Ensure you've set this in your shell
|
||||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
|
||||
if not GITHUB_TOKEN:
|
||||
raise ValueError("GITHUB_TOKEN environment variable not set")
|
||||
|
||||
# Repository information
|
||||
OWNER = "google"
|
||||
REPO = "adk-python"
|
||||
OWNER = os.getenv("OWNER", "google")
|
||||
REPO = os.getenv("REPO", "adk-python")
|
||||
BOT_LABEL = os.getenv("BOT_LABEL", "bot_triaged")
|
||||
|
||||
# Base URL for the GitHub API
|
||||
BASE_URL = "https://api.github.com"
|
||||
|
||||
# Headers including the Authorization header
|
||||
headers = {
|
||||
"Authorization": f"token {GITHUB_TOKEN}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
|
||||
ALLOWED_LABELS = [
|
||||
"documentation",
|
||||
"services",
|
||||
"question",
|
||||
"tools",
|
||||
"eval",
|
||||
"live",
|
||||
"models",
|
||||
"tracing",
|
||||
"core",
|
||||
"web",
|
||||
]
|
||||
|
||||
def list_issues(per_page: int):
|
||||
|
||||
def is_interactive():
|
||||
return os.environ.get("INTERACTIVE", "1").lower() in ["true", "1"]
|
||||
|
||||
|
||||
def list_issues(issue_count: int):
|
||||
"""
|
||||
Generator to list all issues for the repository by handling pagination.
|
||||
|
||||
Args:
|
||||
per_page: number of pages to return per page.
|
||||
issue_count: number of issues to return
|
||||
|
||||
"""
|
||||
state = "open"
|
||||
# only process the 1st page for testing for now
|
||||
page = 1
|
||||
results = []
|
||||
url = ( # :contentReference[oaicite:16]{index=16}
|
||||
f"{BASE_URL}/repos/{OWNER}/{REPO}/issues"
|
||||
)
|
||||
# Warning: let's only handle max 10 issues at a time to avoid bad results
|
||||
params = {"state": state, "per_page": per_page, "page": page}
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status() # :contentReference[oaicite:17]{index=17}
|
||||
issues = response.json()
|
||||
query = f"repo:{OWNER}/{REPO} is:open is:issue no:label"
|
||||
|
||||
unlabelled_issues = []
|
||||
url = f"{BASE_URL}/search/issues"
|
||||
|
||||
params = {
|
||||
"q": query,
|
||||
"sort": "created",
|
||||
"order": "desc",
|
||||
"per_page": issue_count,
|
||||
"page": 1,
|
||||
}
|
||||
response = requests.get(url, headers=headers, params=params, timeout=60)
|
||||
response.raise_for_status()
|
||||
json_response = response.json()
|
||||
issues = json_response.get("items", None)
|
||||
if not issues:
|
||||
return []
|
||||
for issue in issues:
|
||||
# Skip pull requests (issues API returns PRs as well)
|
||||
if "pull_request" in issue:
|
||||
continue
|
||||
results.append(issue)
|
||||
return results
|
||||
if not issue.get("labels", None) or len(issue["labels"]) == 0:
|
||||
unlabelled_issues.append(issue)
|
||||
return unlabelled_issues
|
||||
|
||||
|
||||
def add_label_to_issue(issue_number: str, label: str):
|
||||
@@ -78,41 +90,56 @@ def add_label_to_issue(issue_number: str, label: str):
|
||||
issue_number: issue number of the Github issue, in string foramt.
|
||||
label: label to assign
|
||||
"""
|
||||
print(f"Attempting to add label '{label}' to issue #{issue_number}")
|
||||
if label not in ALLOWED_LABELS:
|
||||
error_message = (
|
||||
f"Error: Label '{label}' is not an allowed label. Will not apply."
|
||||
)
|
||||
print(error_message)
|
||||
return {"status": "error", "message": error_message, "applied_label": None}
|
||||
|
||||
url = f"{BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}/labels"
|
||||
payload = [label]
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
payload = [label, BOT_LABEL]
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=60)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
|
||||
approval_instruction = (
|
||||
"Only label them when the user approves the labeling!"
|
||||
if is_interactive()
|
||||
else (
|
||||
"Do not ask for user approval for labeling! If you can't find a"
|
||||
" appropriate labels for the issue, do not label it."
|
||||
)
|
||||
)
|
||||
|
||||
root_agent = Agent(
|
||||
model="gemini-2.5-pro-preview-05-06",
|
||||
name="adk_triaging_assistant",
|
||||
description="Triage ADK issues.",
|
||||
instruction="""
|
||||
You are a Github adk-python repo triaging bot. You will help get issues, and label them.
|
||||
instruction=f"""
|
||||
You are a Github adk-python repo triaging bot. You will help get issues, and recommend a label.
|
||||
IMPORTANT: {approval_instruction}
|
||||
Here are the rules for labeling:
|
||||
- If the user is asking about documentation-related questions, label it with "documentation".
|
||||
- If it's about session, memory services, label it with "services"
|
||||
- If it's about UI/web, label it with "question"
|
||||
- If it's about UI/web, label it with "web"
|
||||
- If the user is asking about a question, label it with "question"
|
||||
- If it's related to tools, label it with "tools"
|
||||
- If it's about agent evalaution, then label it with "eval".
|
||||
- If it's about streaming/live, label it with "live".
|
||||
- If it's about model support(non-Gemini, like Litellm, Ollama, OpenAI models), label it with "models".
|
||||
- If it's about tracing, label it with "tracing".
|
||||
- If it's agent orchestration, agent definition, label it with "core".
|
||||
- If you can't find a appropriate labels for the issue, return the issues to user to decide.
|
||||
- If you can't find a appropriate labels for the issue, follow the previous instruction that starts with "IMPORTANT:".
|
||||
|
||||
Present the followings in an easy to read format highlighting issue number and your label.
|
||||
- the issue summary in a few sentence
|
||||
- your label recommendation and justification
|
||||
""",
|
||||
tools=[
|
||||
list_issues,
|
||||
add_label_to_issue,
|
||||
],
|
||||
generate_content_config=types.GenerateContentConfig(
|
||||
safety_settings=[
|
||||
types.SafetySetting( # avoid false alarm about rolling dice.
|
||||
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||
threshold=types.HarmBlockThreshold.OFF,
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# Copyright 2025 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.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
|
||||
import agent
|
||||
from dotenv import load_dotenv
|
||||
from google.adk.agents.run_config import RunConfig
|
||||
from google.adk.runners import InMemoryRunner
|
||||
from google.adk.sessions import Session
|
||||
from google.genai import types
|
||||
import requests
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
OWNER = os.getenv("OWNER", "google")
|
||||
REPO = os.getenv("REPO", "adk-python")
|
||||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
|
||||
BASE_URL = "https://api.github.com"
|
||||
headers = {
|
||||
"Authorization": f"token {GITHUB_TOKEN}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
|
||||
if not GITHUB_TOKEN:
|
||||
print(
|
||||
"Warning: GITHUB_TOKEN environment variable not set. API calls might"
|
||||
" fail."
|
||||
)
|
||||
|
||||
|
||||
async def fetch_specific_issue_details(issue_number: int):
|
||||
"""Fetches details for a single issue if it's unlabelled."""
|
||||
if not GITHUB_TOKEN:
|
||||
print("Cannot fetch issue details: GITHUB_TOKEN is not set.")
|
||||
return None
|
||||
|
||||
url = f"{BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}"
|
||||
print(f"Fetching details for specific issue: {url}")
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=60)
|
||||
response.raise_for_status()
|
||||
issue_data = response.json()
|
||||
if not issue_data.get("labels") or len(issue_data["labels"]) == 0:
|
||||
print(f"Issue #{issue_number} is unlabelled. Proceeding.")
|
||||
return {
|
||||
"number": issue_data["number"],
|
||||
"title": issue_data["title"],
|
||||
"body": issue_data.get("body", ""),
|
||||
}
|
||||
else:
|
||||
print(f"Issue #{issue_number} is already labelled. Skipping.")
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching issue #{issue_number}: {e}")
|
||||
if hasattr(e, "response") and e.response is not None:
|
||||
print(f"Response content: {e.response.text}")
|
||||
return None
|
||||
|
||||
|
||||
async def main():
|
||||
app_name = "triage_app"
|
||||
user_id_1 = "triage_user"
|
||||
runner = InMemoryRunner(
|
||||
agent=agent.root_agent,
|
||||
app_name=app_name,
|
||||
)
|
||||
session_11 = await runner.session_service.create_session(
|
||||
app_name=app_name, user_id=user_id_1
|
||||
)
|
||||
|
||||
async def run_agent_prompt(session: Session, prompt_text: str):
|
||||
content = types.Content(
|
||||
role="user", parts=[types.Part.from_text(text=prompt_text)]
|
||||
)
|
||||
print(f"\n>>>> Agent Prompt: {prompt_text}")
|
||||
final_agent_response_parts = []
|
||||
async for event in runner.run_async(
|
||||
user_id=user_id_1,
|
||||
session_id=session.id,
|
||||
new_message=content,
|
||||
run_config=RunConfig(save_input_blobs_as_artifacts=False),
|
||||
):
|
||||
if event.content.parts and event.content.parts[0].text:
|
||||
print(f"** {event.author} (ADK): {event.content.parts[0].text}")
|
||||
if event.author == agent.root_agent.name:
|
||||
final_agent_response_parts.append(event.content.parts[0].text)
|
||||
print(f"<<<< Agent Final Output: {''.join(final_agent_response_parts)}\n")
|
||||
|
||||
event_name = os.getenv("EVENT_NAME")
|
||||
issue_number_str = os.getenv("ISSUE_NUMBER")
|
||||
|
||||
if event_name == "issues" and issue_number_str:
|
||||
print(f"EVENT: Processing specific issue due to '{event_name}' event.")
|
||||
try:
|
||||
issue_number = int(issue_number_str)
|
||||
specific_issue = await fetch_specific_issue_details(issue_number)
|
||||
|
||||
if specific_issue:
|
||||
prompt = (
|
||||
f"A new GitHub issue #{specific_issue['number']} has been opened or"
|
||||
f" reopened. Title: \"{specific_issue['title']}\"\nBody:"
|
||||
f" \"{specific_issue['body']}\"\n\nBased on the rules, recommend an"
|
||||
" appropriate label and its justification."
|
||||
" Then, use the 'add_label_to_issue' tool to apply the label "
|
||||
"directly to this issue."
|
||||
f" The issue number is {specific_issue['number']}."
|
||||
)
|
||||
await run_agent_prompt(session_11, prompt)
|
||||
else:
|
||||
print(
|
||||
f"No unlabelled issue details found for #{issue_number} or an error"
|
||||
" occurred. Skipping agent interaction."
|
||||
)
|
||||
|
||||
except ValueError:
|
||||
print(f"Error: Invalid ISSUE_NUMBER received: {issue_number_str}")
|
||||
|
||||
else:
|
||||
print(f"EVENT: Processing batch of issues (event: {event_name}).")
|
||||
issue_count_str = os.getenv("ISSUE_COUNT_TO_PROCESS", "3")
|
||||
try:
|
||||
num_issues_to_process = int(issue_count_str)
|
||||
except ValueError:
|
||||
print(f"Warning: Invalid ISSUE_COUNT_TO_PROCESS. Defaulting to 3.")
|
||||
num_issues_to_process = 3
|
||||
|
||||
prompt = (
|
||||
f"List the first {num_issues_to_process} unlabelled open issues from"
|
||||
f" the {OWNER}/{REPO} repository. For each issue, provide a summary,"
|
||||
" recommend a label with justification, and then use the"
|
||||
" 'add_label_to_issue' tool to apply the recommended label directly."
|
||||
)
|
||||
await run_agent_prompt(session_11, prompt)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = time.time()
|
||||
print(
|
||||
"Script start time:",
|
||||
time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(start_time)),
|
||||
)
|
||||
print("------------------------------------")
|
||||
asyncio.run(main())
|
||||
end_time = time.time()
|
||||
print("------------------------------------")
|
||||
print(
|
||||
"Script end time:",
|
||||
time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(end_time)),
|
||||
)
|
||||
print("Total script execution time:", f"{end_time - start_time:.2f} seconds")
|
||||
@@ -40,13 +40,28 @@ would set:
|
||||
### With Application Default Credentials
|
||||
|
||||
This mode is useful for quick development when the agent builder is the only
|
||||
user interacting with the agent. The tools are initialized with the default
|
||||
credentials present on the machine running the agent.
|
||||
user interacting with the agent. The tools are run with these credentials.
|
||||
|
||||
1. Create application default credentials on the machine where the agent would
|
||||
be running by following https://cloud.google.com/docs/authentication/provide-credentials-adc.
|
||||
|
||||
1. Set `RUN_WITH_ADC=True` in `agent.py` and run the agent
|
||||
1. Set `CREDENTIALS_TYPE=None` in `agent.py`
|
||||
|
||||
1. Run the agent
|
||||
|
||||
### With Service Account Keys
|
||||
|
||||
This mode is useful for quick development when the agent builder wants to run
|
||||
the agent with service account credentials. The tools are run with these
|
||||
credentials.
|
||||
|
||||
1. Create service account key by following https://cloud.google.com/iam/docs/service-account-creds#user-managed-keys.
|
||||
|
||||
1. Set `CREDENTIALS_TYPE=AuthCredentialTypes.SERVICE_ACCOUNT` in `agent.py`
|
||||
|
||||
1. Download the key file and replace `"service_account_key.json"` with the path
|
||||
|
||||
1. Run the agent
|
||||
|
||||
### With Interactive OAuth
|
||||
|
||||
@@ -72,7 +87,7 @@ type.
|
||||
Note: don't create a separate .env, instead put it to the same .env file that
|
||||
stores your Vertex AI or Dev ML credentials
|
||||
|
||||
1. Set `RUN_WITH_ADC=False` in `agent.py` and run the agent
|
||||
1. Set `CREDENTIALS_TYPE=AuthCredentialTypes.OAUTH2` in `agent.py` and run the agent
|
||||
|
||||
## Sample prompts
|
||||
|
||||
|
||||
@@ -15,24 +15,21 @@
|
||||
import os
|
||||
|
||||
from google.adk.agents import llm_agent
|
||||
from google.adk.auth import AuthCredentialTypes
|
||||
from google.adk.tools.bigquery import BigQueryCredentialsConfig
|
||||
from google.adk.tools.bigquery import BigQueryToolset
|
||||
from google.adk.tools.bigquery.config import BigQueryToolConfig
|
||||
from google.adk.tools.bigquery.config import WriteMode
|
||||
import google.auth
|
||||
|
||||
RUN_WITH_ADC = False
|
||||
# Define an appropriate credential type
|
||||
CREDENTIALS_TYPE = AuthCredentialTypes.OAUTH2
|
||||
|
||||
|
||||
# Define BigQuery tool config
|
||||
tool_config = BigQueryToolConfig(write_mode=WriteMode.ALLOWED)
|
||||
|
||||
if RUN_WITH_ADC:
|
||||
# Initialize the tools to use the application default credentials.
|
||||
application_default_credentials, _ = google.auth.default()
|
||||
credentials_config = BigQueryCredentialsConfig(
|
||||
credentials=application_default_credentials
|
||||
)
|
||||
else:
|
||||
if CREDENTIALS_TYPE == AuthCredentialTypes.OAUTH2:
|
||||
# Initiaze the tools to do interactive OAuth
|
||||
# The environment variables OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET
|
||||
# must be set
|
||||
@@ -40,6 +37,20 @@ else:
|
||||
client_id=os.getenv("OAUTH_CLIENT_ID"),
|
||||
client_secret=os.getenv("OAUTH_CLIENT_SECRET"),
|
||||
)
|
||||
elif CREDENTIALS_TYPE == AuthCredentialTypes.SERVICE_ACCOUNT:
|
||||
# Initialize the tools to use the credentials in the service account key.
|
||||
# If this flow is enabled, make sure to replace the file path with your own
|
||||
# service account key file
|
||||
# https://cloud.google.com/iam/docs/service-account-creds#user-managed-keys
|
||||
creds, _ = google.auth.load_credentials_from_file("service_account_key.json")
|
||||
credentials_config = BigQueryCredentialsConfig(credentials=creds)
|
||||
else:
|
||||
# Initialize the tools to use the application default credentials.
|
||||
# https://cloud.google.com/docs/authentication/provide-credentials-adc
|
||||
application_default_credentials, _ = google.auth.default()
|
||||
credentials_config = BigQueryCredentialsConfig(
|
||||
credentials=application_default_credentials
|
||||
)
|
||||
|
||||
bigquery_toolset = BigQueryToolset(
|
||||
credentials_config=credentials_config, bigquery_tool_config=tool_config
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import random
|
||||
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.examples.example import Example
|
||||
from google.adk.tools.example_tool import ExampleTool
|
||||
from google.genai import types
|
||||
|
||||
@@ -66,43 +67,47 @@ def check_prime(nums: list[int]) -> str:
|
||||
)
|
||||
|
||||
|
||||
example_tool = ExampleTool([
|
||||
{
|
||||
"input": {
|
||||
"role": "user",
|
||||
"parts": [{"text": "Roll a 6-sided die."}],
|
||||
},
|
||||
"output": [
|
||||
{"role": "model", "parts": [{"text": "I rolled a 4 for you."}]}
|
||||
],
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"role": "user",
|
||||
"parts": [{"text": "Is 7 a prime number?"}],
|
||||
},
|
||||
"output": [{
|
||||
"role": "model",
|
||||
"parts": [{"text": "Yes, 7 is a prime number."}],
|
||||
}],
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"role": "user",
|
||||
"parts": [{"text": "Roll a 10-sided die and check if it's prime."}],
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"role": "model",
|
||||
"parts": [{"text": "I rolled an 8 for you."}],
|
||||
},
|
||||
{
|
||||
"role": "model",
|
||||
"parts": [{"text": "8 is not a prime number."}],
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
example_tool = ExampleTool(
|
||||
examples=[
|
||||
Example(
|
||||
input=types.UserContent(
|
||||
parts=[types.Part(text="Roll a 6-sided die.")]
|
||||
),
|
||||
output=[
|
||||
types.ModelContent(
|
||||
parts=[types.Part(text="I rolled a 4 for you.")]
|
||||
)
|
||||
],
|
||||
),
|
||||
Example(
|
||||
input=types.UserContent(
|
||||
parts=[types.Part(text="Is 7 a prime number?")]
|
||||
),
|
||||
output=[
|
||||
types.ModelContent(
|
||||
parts=[types.Part(text="Yes, 7 is a prime number.")]
|
||||
)
|
||||
],
|
||||
),
|
||||
Example(
|
||||
input=types.UserContent(
|
||||
parts=[
|
||||
types.Part(
|
||||
text="Roll a 10-sided die and check if it's prime."
|
||||
)
|
||||
]
|
||||
),
|
||||
output=[
|
||||
types.ModelContent(
|
||||
parts=[types.Part(text="I rolled an 8 for you.")]
|
||||
),
|
||||
types.ModelContent(
|
||||
parts=[types.Part(text="8 is not a prime number.")]
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
prime_agent = Agent(
|
||||
name="prime_agent",
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2025 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.
|
||||
|
||||
from . import agent
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
# Copyright 2025 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.
|
||||
|
||||
import random
|
||||
|
||||
from google.adk import Agent
|
||||
from google.adk.tools.tool_context import ToolContext
|
||||
from google.genai import types
|
||||
|
||||
|
||||
def roll_die(sides: int, tool_context: ToolContext) -> int:
|
||||
"""Roll a die and return the rolled result.
|
||||
|
||||
Args:
|
||||
sides: The integer number of sides the die has.
|
||||
|
||||
Returns:
|
||||
An integer of the result of rolling the die.
|
||||
"""
|
||||
result = random.randint(1, sides)
|
||||
if not 'rolls' in tool_context.state:
|
||||
tool_context.state['rolls'] = []
|
||||
|
||||
tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
|
||||
return result
|
||||
|
||||
|
||||
async def check_prime(nums: list[int]) -> str:
|
||||
"""Check if a given list of numbers are prime.
|
||||
|
||||
Args:
|
||||
nums: The list of numbers to check.
|
||||
|
||||
Returns:
|
||||
A str indicating which number is prime.
|
||||
"""
|
||||
primes = set()
|
||||
for number in nums:
|
||||
number = int(number)
|
||||
if number <= 1:
|
||||
continue
|
||||
is_prime = True
|
||||
for i in range(2, int(number**0.5) + 1):
|
||||
if number % i == 0:
|
||||
is_prime = False
|
||||
break
|
||||
if is_prime:
|
||||
primes.add(number)
|
||||
return (
|
||||
'No prime numbers found.'
|
||||
if not primes
|
||||
else f"{', '.join(str(num) for num in primes)} are prime numbers."
|
||||
)
|
||||
|
||||
|
||||
root_agent = Agent(
|
||||
model='gemini-2.0-flash-live-preview-04-09', # for Vertex project
|
||||
# model='gemini-2.0-flash-live-001', # for AI studio key
|
||||
name='hello_world_agent',
|
||||
description=(
|
||||
'hello world agent that can roll a dice of 8 sides and check prime'
|
||||
' numbers.'
|
||||
),
|
||||
instruction="""
|
||||
You roll dice and answer questions about the outcome of the dice rolls.
|
||||
You can roll dice of different sizes.
|
||||
You can use multiple tools in parallel by calling functions in parallel(in one request and in one round).
|
||||
It is ok to discuss previous dice roles, and comment on the dice rolls.
|
||||
When you are asked to roll a die, you must call the roll_die tool with the number of sides. Be sure to pass in an integer. Do not pass in a string.
|
||||
You should never roll a die on your own.
|
||||
When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string.
|
||||
You should not check prime numbers before calling the tool.
|
||||
When you are asked to roll a die and check prime numbers, you should always make the following two function calls:
|
||||
1. You should first call the roll_die tool to get a roll. Wait for the function response before calling the check_prime tool.
|
||||
2. After you get the function response from roll_die tool, you should call the check_prime tool with the roll_die result.
|
||||
2.1 If user asks you to check primes based on previous rolls, make sure you include the previous rolls in the list.
|
||||
3. When you respond, you must include the roll_die result from step 1.
|
||||
You should always perform the previous 3 steps when asking for a roll and checking prime numbers.
|
||||
You should not rely on the previous history on prime results.
|
||||
""",
|
||||
tools=[
|
||||
roll_die,
|
||||
check_prime,
|
||||
],
|
||||
generate_content_config=types.GenerateContentConfig(
|
||||
safety_settings=[
|
||||
types.SafetySetting( # avoid false alarm about rolling dice.
|
||||
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||
threshold=types.HarmBlockThreshold.OFF,
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
# Simplistic Live (Bidi-Streaming) Agent
|
||||
This project provides a basic example of a live, bidirectional streaming agent
|
||||
designed for testing and experimentation.
|
||||
|
||||
You can see full documentation [here](https://google.github.io/adk-docs/streaming/).
|
||||
|
||||
## Getting Started
|
||||
|
||||
Follow these steps to get the agent up and running:
|
||||
|
||||
1. **Start the ADK Web Server**
|
||||
Open your terminal, navigate to the root directory that contains the
|
||||
`live_bidi_streaming_agent` folder, and execute the following command:
|
||||
```bash
|
||||
adk web
|
||||
```
|
||||
|
||||
2. **Access the ADK Web UI**
|
||||
Once the server is running, open your web browser and navigate to the URL
|
||||
provided in the terminal (it will typically be `http://localhost:8000`).
|
||||
|
||||
3. **Select the Agent**
|
||||
In the top-left corner of the ADK Web UI, use the dropdown menu to select
|
||||
this agent.
|
||||
|
||||
4. **Start Streaming**
|
||||
Click on either the **Audio** or **Video** icon located near the chat input
|
||||
box to begin the streaming session.
|
||||
|
||||
5. **Interact with the Agent**
|
||||
You can now begin talking to the agent, and it will respond in real-time.
|
||||
|
||||
## Usage Notes
|
||||
|
||||
* You only need to click the **Audio** or **Video** button once to initiate the
|
||||
stream. The current version does not support stopping and restarting the stream
|
||||
by clicking the button again during a session.
|
||||
@@ -16,8 +16,8 @@
|
||||
import os
|
||||
|
||||
from google.adk.agents.llm_agent import LlmAgent
|
||||
from google.adk.tools.mcp_tool.mcp_session_manager import SseConnectionParams
|
||||
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
|
||||
from google.adk.tools.mcp_tool.mcp_toolset import SseServerParams
|
||||
|
||||
_allowed_path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
@@ -31,7 +31,7 @@ Allowed directory: {_allowed_path}
|
||||
""",
|
||||
tools=[
|
||||
MCPToolset(
|
||||
connection_params=SseServerParams(
|
||||
connection_params=SseConnectionParams(
|
||||
url='http://localhost:3000/sse',
|
||||
headers={'Accept': 'text/event-stream'},
|
||||
),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
This agent connects to a local MCP server via sse.
|
||||
This agent connects to a local MCP server via Streamable HTTP.
|
||||
|
||||
To run this agent, start the local MCP server first by :
|
||||
|
||||
```bash
|
||||
uv run filesystem_server.py
|
||||
```
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import os
|
||||
from google.adk.agents.llm_agent import LlmAgent
|
||||
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPServerParams
|
||||
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
|
||||
from google.adk.tools.mcp_tool.mcp_toolset import SseServerParams
|
||||
|
||||
_allowed_path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ def get_weather(city: str) -> dict:
|
||||
"status": "success",
|
||||
"report": (
|
||||
"The weather in New York is sunny with a temperature of 25 degrees"
|
||||
" Celsius (41 degrees Fahrenheit)."
|
||||
" Celsius (77 degrees Fahrenheit)."
|
||||
),
|
||||
}
|
||||
else:
|
||||
|
||||
+36
-19
@@ -25,27 +25,32 @@ classifiers = [ # List of https://pypi.org/classifiers/
|
||||
]
|
||||
dependencies = [
|
||||
# go/keep-sorted start
|
||||
"authlib>=1.5.1", # For RestAPI Tool
|
||||
"click>=8.1.8", # For CLI tools
|
||||
"fastapi>=0.115.0", # FastAPI framework
|
||||
"google-api-python-client>=2.157.0", # Google API client discovery
|
||||
"google-cloud-aiplatform[agent_engines]>=1.95.1", # For VertexAI integrations, e.g. example store.
|
||||
"google-cloud-secret-manager>=2.22.0", # Fetching secrets in RestAPI Tool
|
||||
"google-cloud-speech>=2.30.0", # For Audio Transcription
|
||||
"google-cloud-storage>=2.18.0, <3.0.0", # For GCS Artifact service
|
||||
"google-genai>=1.17.0", # Google GenAI SDK
|
||||
"graphviz>=0.20.2", # Graphviz for graph rendering
|
||||
"mcp>=1.8.0;python_version>='3.10'", # For MCP Toolset
|
||||
"opentelemetry-api>=1.31.0", # OpenTelemetry
|
||||
"anyio>=4.9.0;python_version>='3.10'", # For MCP Session Manager
|
||||
"authlib>=1.5.1", # For RestAPI Tool
|
||||
"click>=8.1.8", # For CLI tools
|
||||
"fastapi>=0.115.0", # FastAPI framework
|
||||
"google-api-python-client>=2.157.0", # Google API client discovery
|
||||
"google-cloud-aiplatform[agent_engines]>=1.95.1", # For VertexAI integrations, e.g. example store.
|
||||
"google-cloud-secret-manager>=2.22.0", # Fetching secrets in RestAPI Tool
|
||||
"google-cloud-speech>=2.30.0", # For Audio Transcription
|
||||
"google-cloud-storage>=2.18.0, <3.0.0", # For GCS Artifact service
|
||||
"google-genai>=1.17.0", # Google GenAI SDK
|
||||
"graphviz>=0.20.2", # Graphviz for graph rendering
|
||||
"mcp>=1.8.0;python_version>='3.10'", # For MCP Toolset
|
||||
"opentelemetry-api>=1.31.0", # OpenTelemetry
|
||||
"opentelemetry-exporter-gcp-trace>=1.9.0",
|
||||
"opentelemetry-sdk>=1.31.0",
|
||||
"pydantic>=2.0, <3.0.0", # For data validation/models
|
||||
"python-dotenv>=1.0.0", # To manage environment variables
|
||||
"PyYAML>=6.0.2", # For APIHubToolset.
|
||||
"sqlalchemy>=2.0", # SQL database ORM
|
||||
"tzlocal>=5.3", # Time zone utilities
|
||||
"pydantic>=2.0, <3.0.0", # For data validation/models
|
||||
"python-dateutil>=2.9.0.post0", # For Vertext AI Session Service
|
||||
"python-dotenv>=1.0.0", # To manage environment variables
|
||||
"PyYAML>=6.0.2", # For APIHubToolset.
|
||||
"requests>=2.32.4",
|
||||
"sqlalchemy>=2.0", # SQL database ORM
|
||||
"starlette>=0.46.2", # For FastAPI CLI
|
||||
"typing-extensions>=4.5, <5",
|
||||
"uvicorn>=0.34.0", # ASGI server for FastAPI
|
||||
"tzlocal>=5.3", # Time zone utilities
|
||||
"uvicorn>=0.34.0", # ASGI server for FastAPI
|
||||
"websockets>=15.0.1", # For BaseLlmFlow
|
||||
# go/keep-sorted end
|
||||
]
|
||||
dynamic = ["version"]
|
||||
@@ -71,6 +76,12 @@ dev = [
|
||||
# go/keep-sorted end
|
||||
]
|
||||
|
||||
a2a = [
|
||||
# go/keep-sorted start
|
||||
"a2a-sdk>=0.2.7;python_version>='3.10'"
|
||||
# go/keep-sorted end
|
||||
]
|
||||
|
||||
eval = [
|
||||
# go/keep-sorted start
|
||||
"google-cloud-aiplatform[evaluation]>=1.87.0",
|
||||
@@ -84,7 +95,7 @@ test = [
|
||||
"anthropic>=0.43.0", # For anthropic model tests
|
||||
"langchain-community>=0.3.17",
|
||||
"langgraph>=0.2.60", # For LangGraphAgent
|
||||
"litellm>=1.71.2", # For LiteLLM tests
|
||||
"litellm>=1.71.2", # For LiteLLM tests
|
||||
"llama-index-readers-file>=0.4.0", # For retrieval tests
|
||||
|
||||
"pytest-asyncio>=0.25.0",
|
||||
@@ -140,24 +151,30 @@ pyink-annotation-pragmas = [
|
||||
requires = ["flit_core >=3.8,<4"]
|
||||
build-backend = "flit_core.buildapi"
|
||||
|
||||
|
||||
[tool.flit.sdist]
|
||||
include = ['src/**/*', 'README.md', 'pyproject.toml', 'LICENSE']
|
||||
exclude = ['src/**/*.sh']
|
||||
|
||||
|
||||
[tool.flit.module]
|
||||
name = "google.adk"
|
||||
include = ["py.typed"]
|
||||
|
||||
|
||||
[tool.isort]
|
||||
profile = "google"
|
||||
single_line_exclusions = []
|
||||
line_length = 200 # Prevent line wrap flickering.
|
||||
known_third_party = ["google.adk"]
|
||||
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
asyncio_default_fixture_loop_scope = "function"
|
||||
asyncio_mode = "auto"
|
||||
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.9"
|
||||
exclude = "tests/"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright 2025 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.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright 2025 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.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user