Skip to content

Commit 07ad687

Browse files
committed
feat(adk): Implement core data classes
1 parent 14ee002 commit 07ad687

File tree

3 files changed

+169
-3
lines changed

3 files changed

+169
-3
lines changed

packages/toolbox-adk/src/toolbox_adk/__init__.py

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

15-
from .version import __version__
16-
from .credentials import CredentialStrategy, CredentialConfig, CredentialType
1715
from .client import ToolboxClient
18-
from .tool import ToolboxTool, ToolboxContext
16+
from .credentials import CredentialConfig, CredentialStrategy, CredentialType
17+
from .tool import ToolboxContext, ToolboxTool
1918
from .toolset import ToolboxToolset
19+
from .version import __version__
2020

2121
__all__ = [
2222
"CredentialStrategy",
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from dataclasses import dataclass
16+
from enum import Enum
17+
from typing import Any, Dict, List, Optional
18+
19+
from google.auth import credentials as google_creds
20+
21+
22+
class CredentialType(Enum):
23+
TOOLBOX_IDENTITY = "TOOLBOX_IDENTITY"
24+
APPLICATION_DEFAULT_CREDENTIALS = "APPLICATION_DEFAULT_CREDENTIALS"
25+
USER_IDENTITY = "USER_IDENTITY"
26+
MANUAL_TOKEN = "MANUAL_TOKEN"
27+
MANUAL_CREDS = "MANUAL_CREDS"
28+
29+
30+
@dataclass
31+
class CredentialConfig:
32+
type: CredentialType
33+
# For APPLICATION_DEFAULT_CREDENTIALS
34+
target_audience: Optional[str] = None
35+
# For USER_IDENTITY
36+
client_id: Optional[str] = None
37+
client_secret: Optional[str] = None
38+
scopes: Optional[List[str]] = None
39+
# For MANUAL_TOKEN
40+
token: Optional[str] = None
41+
scheme: Optional[str] = None
42+
# For MANUAL_CREDS
43+
credentials: Optional[Any] = None # google.auth.credentials.Credentials
44+
45+
46+
class CredentialStrategy:
47+
"""Factory for creating credential configurations for ToolboxToolset."""
48+
49+
@staticmethod
50+
def TOOLBOX_IDENTITY() -> CredentialConfig:
51+
"""
52+
No credentials are sent. Relies on the remote Toolbox server's own identity.
53+
"""
54+
return CredentialConfig(type=CredentialType.TOOLBOX_IDENTITY)
55+
56+
@staticmethod
57+
def APPLICATION_DEFAULT_CREDENTIALS(target_audience: str) -> CredentialConfig:
58+
"""
59+
Uses the agent ADC to generate a Google-signed ID token for the specified audience.
60+
This is suitable for Cloud Run, GKE, or local development with `gcloud auth login`.
61+
"""
62+
return CredentialConfig(
63+
type=CredentialType.APPLICATION_DEFAULT_CREDENTIALS,
64+
target_audience=target_audience,
65+
)
66+
67+
@staticmethod
68+
def WORKLOAD_IDENTITY(target_audience: str) -> CredentialConfig:
69+
"""
70+
Alias for APPLICATION_DEFAULT_CREDENTIALS.
71+
"""
72+
return CredentialStrategy.APPLICATION_DEFAULT_CREDENTIALS(target_audience)
73+
74+
@staticmethod
75+
def USER_IDENTITY(
76+
client_id: str, client_secret: str, scopes: Optional[List[str]] = None
77+
) -> CredentialConfig:
78+
"""
79+
Configures the ADK-native interactive 3-legged OAuth flow to get consent
80+
and credentials from the end-user at runtime.
81+
"""
82+
return CredentialConfig(
83+
type=CredentialType.USER_IDENTITY,
84+
client_id=client_id,
85+
client_secret=client_secret,
86+
scopes=scopes,
87+
)
88+
89+
@staticmethod
90+
def MANUAL_TOKEN(token: str, scheme: str = "Bearer") -> CredentialConfig:
91+
"""
92+
Send a hardcoded token string in the Authorization header.
93+
"""
94+
return CredentialConfig(
95+
type=CredentialType.MANUAL_TOKEN,
96+
token=token,
97+
scheme=scheme,
98+
)
99+
100+
@staticmethod
101+
def MANUAL_CREDS(credentials: Any) -> CredentialConfig:
102+
"""
103+
Uses a provided Google Auth Credentials object.
104+
"""
105+
return CredentialConfig(
106+
type=CredentialType.MANUAL_CREDS,
107+
credentials=credentials,
108+
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from toolbox_adk.credentials import CredentialStrategy, CredentialType
16+
17+
18+
class TestCredentialStrategy:
19+
def test_toolbox_identity(self):
20+
config = CredentialStrategy.TOOLBOX_IDENTITY()
21+
assert config.type == CredentialType.TOOLBOX_IDENTITY
22+
23+
def test_application_default_credentials(self):
24+
audience = "https://example.com"
25+
config = CredentialStrategy.APPLICATION_DEFAULT_CREDENTIALS(audience)
26+
assert config.type == CredentialType.APPLICATION_DEFAULT_CREDENTIALS
27+
assert config.target_audience == audience
28+
29+
def test_workload_identity_alias(self):
30+
audience = "https://example.com"
31+
config = CredentialStrategy.WORKLOAD_IDENTITY(audience)
32+
assert config.type == CredentialType.APPLICATION_DEFAULT_CREDENTIALS
33+
assert config.target_audience == audience
34+
35+
def test_user_identity(self):
36+
config = CredentialStrategy.USER_IDENTITY(
37+
client_id="id", client_secret="secret", scopes=["scope1"]
38+
)
39+
assert config.type == CredentialType.USER_IDENTITY
40+
assert config.client_id == "id"
41+
assert config.client_secret == "secret"
42+
assert config.scopes == ["scope1"]
43+
44+
def test_manual_token(self):
45+
config = CredentialStrategy.MANUAL_TOKEN(token="abc", scheme="Custom")
46+
assert config.type == CredentialType.MANUAL_TOKEN
47+
assert config.token == "abc"
48+
assert config.scheme == "Custom"
49+
50+
def test_manual_token_defaults(self):
51+
config = CredentialStrategy.MANUAL_TOKEN(token="abc")
52+
assert config.scheme == "Bearer"
53+
54+
def test_manual_creds(self):
55+
fake_creds = object()
56+
config = CredentialStrategy.MANUAL_CREDS(fake_creds)
57+
assert config.type == CredentialType.MANUAL_CREDS
58+
assert config.credentials == fake_creds

0 commit comments

Comments
 (0)