8000 Changes for 0.1.0 release · codefromthecrypt/adk-python@363e106 · GitHub
[go: up one dir, main page]

Skip to content

Commit 363e106

Browse files
committed
Changes for 0.1.0 release
1 parent 9827820 commit 363e106

25 files changed

+553
-99
lines changed

README.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
44

5-
<img src="assets/agent-development-kit.png" alt="Agent Development Kit Logo" width="150">
6-
7-
**An open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.**
5+
<html>
6+
<h1 align="center">
7+
<img src="assets/agent-development-kit.png" width="256"/>
8+
</h1>
9+
<h3 align="center">
10+
An open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
11+
</h3>
12+
<h3 align="center">
13+
Important Links:
14+
<a href="https://google.github.io/adk-docs/">Docs</a> &
15+
<a href="https://github.com/google/adk-samples">Samples</a>.
16+
</h3>
17+
</html>
818

919
The Agent Development Kit (ADK) is designed for developers seeking fine-grained control and flexibility when building advanced AI agents that are tightly integrated with services in Google Cloud. It allows you to define agent behavior, orchestration, and tool use directly in code, enabling robust debugging, versioning, and deployment anywhere – from your laptop to the cloud.
1020

@@ -25,7 +35,7 @@ The Agent Development Kit (ADK) is designed for developers seeking fine-grained
2535

2636
## 🚀 Installation
2737

28-
You can install the Agent Developer Kit using `pip`:
38+
You can install the ADK using `pip`:
2939

3040
```bash
3141
pip install google-adk
@@ -42,7 +52,7 @@ from google.adk.tools import google_search
4252

4353
root_agent = Agent(
4454
name="search_assistant",
45-
model="gemini-1.5-flash-latest", # Or your preferred model like gemini-2.0-flash-001
55+
model="gemini-2.0-flash-exp", # Or your preferred Gemini model
4656
instruction="You are a helpful assistant. Answer user questions using Google Search when needed.",
4757
description="An assistant that can search the web.",
4858
tools=[google_search]
@@ -68,19 +78,18 @@ Or launch the Web UI from the folder that contains `my_agent` folder:
6878
adk web
6979
```
7080

71-
For a full step-by-step guide F438 , check out the quickstart or sample agents.
81+
For a full step-by-step guide, check out the [quickstart](https://google.github.io/adk-docs/get-started/quickstart/) or [sample agents](https://github.com/google/adk-samples).
7282

7383
## 📚 Resources
7484

7585
Explore the full documentation for detailed guides on building, evaluating, and deploying agents:
7686

77-
* **[Get Started](get-started/introduction.md)**
78-
* **[Build Agents](build/agents.md)**
79-
* **[Browse Sample Agents](learn/sample_agents/)**
80-
* **[Evaluate Agents](evaluate/evaluate-agents.md)**
81-
* **[Deploy Agents](deploy/overview.md)**
82-
* **[API Reference](guides/reference.md)**
83-
* **[Troubleshooting](guides/troubleshooting.md)**
87+
* **[Get Started](https://google.github.io/adk-docs/get-started/)**
88+
* **[Browse Sample Agents](https://github.com/google/adk-samples)**
89+
* **[Evaluate Agents](https://google.github.io/adk-docs/guides/evaluate-agents/)**
90+
* **[Deploy Agents](https://google.github.io/adk-docs/deploy/)**
91+
* **[API Reference](https://google.github.io/adk-docs/api-reference/)**
92+
* **[Troubleshooting](https://google.github.io/adk-docs/guides/troubleshooting/)**
8493

8594
## 🤝 Contributing
8695

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ requires = ["flit_core >=3.8,<4"]
124124
build-backend = "flit_core.buildapi"
125125

126126
[tool.flit.sdist]
127-
include = ['src/**/*', 'README.md', 'pyproject.toml']
127+
include = ['src/**/*', 'README.md', 'pyproject.toml', 'LICENSE']
128128
exclude = ['src/**/*.sh']
129129

130130
[tool.flit.module]
@@ -135,7 +135,6 @@ name = "google.adk"
135135
force_single_line = true
136136
force_sort_within_sections = true
137137
honor_case_in_force_sorted_sections = true
138-
known_third_party = ["agents", "google"]
139138
order_by_type = false
140139
sort_relative_in_force_sorted_sections = true
141140
multi_line_output = 3

src/google/adk/agents/run_config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class RunConfig(BaseModel):
5252
Whether to support CFC (Compositional Function Calling). Only applicable for
5353
StreamingMode.SSE. If it's true. the LIVE API will be invoked. Since only LIVE
5454
API supports CFC
55+
56+
.. warning::
57+
This feature is **experimental** and its API or behavior may change
58+
in future releases.
5559
"""
5660

5761
streaming_mode: StreamingMode = StreamingMode.NONE

src/google/adk/auth/auth_handler.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def exchange_auth_token(
8989
client = OAuth2Session(
9090
auth_credential.oauth2.client_id,
9191
auth_credential.oauth2.client_secret,
92-
scope=",".join(scopes),
92+
scope=" ".join(scopes),
9393
redirect_uri=auth_credential.oauth2.redirect_uri,
9494
state=auth_credential.oauth2.state,
9595
)
@@ -250,14 +250,17 @@ def generate_auth_uri(
250250
or auth_scheme.flows.password
251251
and auth_scheme.flows.password.scopes
252252
)
253+
scopes = list(scopes.keys())
253254

254255
client = OAuth2Session(
255256
auth_credential.oauth2.client_id,
256257
auth_credential.oauth2.client_secret,
257258
scope=" ".join(scopes),
258259
redirect_uri=auth_credential.oauth2.redirect_uri,
259260
)
260-
uri, state = client.create_authorization_url(url=authorization_endpoint)
261+
uri, state = client.create_authorization_url(
262+
url=authorization_endpoint, access_type="offline", prompt="consent"
263+
)
261264
exchanged_auth_credential = auth_credential.model_copy(deep=True)
262265
exchanged_auth_credential.oauth2.auth_uri = uri
263266
exchanged_auth_credential.oauth2.state = state

src/google/adk/auth/auth_preprocessor.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,28 @@ async def run_async(
4848
events = invocation_context.session.events
4949
if not events:
5050
return
51-
request_euc_function_call_response_event = events[-1]
52-
responses = (
53-
request_euc_function_call_response_event.get_function_responses()
54-
)
55-
if not responses:
56-
return
5751

5852
request_euc_function_call_ids = set()
59-
60-
for function_call_response in responses:
61-
if function_call_response.name != REQUEST_EUC_FUNCTION_CALL_NAME:
53+
for k in range(len(events) - 1, -1, -1):
54+
event = events[k]
55+
# look for first event authored by user
56+
if not event.author or event.author != 'user':
6257
continue
58+
responses = event.get_function_responses()
59+
if not responses:
60+
return
6361

64-
# found the function call response for the system long running request euc
65-
# function call
66-
request_euc_function_call_ids.add(function_call_response.id)
67-
auth_config = AuthConfig.model_validate(function_call_response.response)
68-
AuthHandler(auth_config=auth_config).parse_and_store_auth_response(
69-
state=invocation_context.session.state
70-
)
62+
for function_call_response in responses:
63+
if function_call_response.name != REQUEST_EUC_FUNCTION_CALL_NAME:
64+
continue
65+
# found the function call response for the system long running request euc
66+
# function call
67+
request_euc_function_call_ids.add(function_call_response.id)
68+
auth_config = AuthConfig.model_validate(function_call_response.response)
69+
AuthHandler(auth_config=auth_config).parse_and_store_auth_response(
70+
state=invocation_context.session.state
71+
)
72+
break
7173

7274
if not request_euc_function_call_ids:
7375
return
@@ -89,6 +91,7 @@ async def run_async(
8991
tools_to_resume.add(args.function_call_id)
9092
if not tools_to_resume:
9193
continue
94+
9295
# found the the system long running reqeust euc function call
9396
# looking for original function call that requests euc
9497
for j in range(i - 1, -1, -1):

src/google/adk/cli/agent_graph.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
17+
import logging
1518
from typing import Union
1619

1720
import graphviz
@@ -21,7 +24,15 @@
2124
from ..tools.agent_tool import AgentTool
2225
from ..tools.base_tool import BaseTool
2326
from ..tools.function_tool import FunctionTool
24-
from ..tools.retrieval.base_retrieval_tool import BaseRetrievalTool
27+
28+
logger = logging.getLogger(__name__)
29+
30+
try:
31+
from ..tools.retrieval.base_retrieval_tool import BaseRetrievalTool
32+
except ModuleNotFoundError:
33+
retrieval_tool_module_loaded = False
34+
else:
35+
retrieval_tool_module_loaded = True
2536

2637

2738
def build_graph(graph, agent: BaseAgent, highlight_pairs):
@@ -38,9 +49,12 @@ def get_node_name(tool_or_agent: Union[BaseAgent, BaseTool]):
3849
raise ValueError(f'Unsupported tool type: {tool_or_agent}')
3950

4051
def get_node_caption(tool_or_agent: Union[BaseAgent, BaseTool]):
52+
4153
if isinstance(tool_or_agent, BaseAgent):
4254
return '🤖 ' + tool_or_agent.name
43-
elif isinstance(tool_or_agent, BaseRetrievalTool):
55+
elif retrieval_tool_module_loaded and isinstance(
56+
tool_or_agent, BaseRetrievalTool
57+
):
4458
return '🔎 ' + tool_or_agent.name
4559
elif isinstance(tool_or_agent, FunctionTool):
4660
return '🔧 ' + tool_or_agent.name
@@ -49,19 +63,31 @@ def get_node_caption(tool_or_agent: Union[BaseAgent, BaseTool]):
4963
elif isinstance(tool_or_agent, BaseTool):
5064
return '🔧 ' + tool_or_agent.name
5165
else:
52-
raise ValueError(f'Unsupported tool type: {type(tool)}')
66+
logger.warning(
67+
'Unsupported tool, type: %s, obj: %s',
68+
type(tool_or_agent),
69+
tool_or_agent,
70+
)
71+
return f'❓ Unsupported tool type: {type(tool_or_agent)}'
5372

5473
def get_node_shape(tool_or_agent: Union[BaseAgent, BaseTool]):
5574
if isinstance(tool_or_agent, BaseAgent):
5675
return 'ellipse'
57-
elif isinstance(tool_or_agent, BaseRetrievalTool):
76+
elif retrieval_tool_module_loaded and isinstance(
77+
tool_or_agent, BaseRetrievalTool
78+
):
5879
return 'cylinder'
5980
elif isinstance(tool_or_agent, FunctionTool):
6081
return 'box'
6182
elif isinstance(tool_or_agent, BaseTool):
6283
return 'box'
6384
else:
64-
raise ValueError(f'Unsupported tool type: {type(tool_or_agent)}')
85+
logger.warning(
86+
'Unsupported tool, type: %s, obj: %s',
87+
type(tool_or_agent),
88+
tool_or_agent,
89+
)
90+
return 'cylinder'
6591

6692
def draw_node(tool_or_agent: Union[BaseAgent, BaseTool]):
6793
name = get_node_name(tool_or_agent)
Lines changed: 17 additions & 0 deletions
Loading
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
class AudioProcessor extends AudioWorkletProcessor {
18+
constructor() {
19+
super();
20+
this.targetSampleRate = 22000; // Change to your desired rate
21+
this.originalSampleRate = sampleRate; // Browser's sample rate
22+
this.resampleRatio = this.originalSampleRate / this.targetSampleRate;
23+
}
24+
25+
process(inputs, outputs, parameters) {
26+
const input = inputs[0];
27+
if (input.length > 0) {
28+
let audioData = input[0]; // Get first channel's data
29+
30+
if (this.resampleRatio !== 1) {
31+
audioData = this.resample(audioData);
32+
}
33+
34+
this.port.postMessage(audioData);
35+
}
36+
return true; // Keep processor alive
37+
}
38+
39+
resample(audioData) {
40+
const newLength = Math.round(audioData.length / this.resampleRatio);
41+
const resampled = new Float32Array(newLength);
42+
43+
for (let i = 0; i < newLength; i++) {
44+
const srcIndex = Math.floor(i * this.resampleRatio);
45+
resampled[i] = audioData[srcIndex]; // Nearest neighbor resampling
46+
}
47+
return resampled;
48+
}
49+
}
50+
51+
registerProcessor('audio-processor', AudioProcessor);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"backendUrl": ""
3+
}

0 commit comments

Comments
 (0)
0