google-adk-extras 0.2.6__py3-none-any.whl → 0.2.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google_adk_extras/__init__.py +3 -3
- google_adk_extras/adk_builder.py +15 -292
- google_adk_extras/artifacts/local_folder_artifact_service.py +0 -2
- google_adk_extras/artifacts/mongo_artifact_service.py +0 -1
- google_adk_extras/artifacts/s3_artifact_service.py +0 -1
- google_adk_extras/artifacts/sql_artifact_service.py +0 -1
- google_adk_extras/custom_agent_loader.py +1 -1
- google_adk_extras/enhanced_adk_web_server.py +0 -2
- google_adk_extras/enhanced_fastapi.py +0 -1
- google_adk_extras/memory/mongo_memory_service.py +0 -1
- google_adk_extras/memory/sql_memory_service.py +1 -1
- google_adk_extras/memory/yaml_file_memory_service.py +1 -3
- google_adk_extras/sessions/mongo_session_service.py +0 -1
- google_adk_extras/sessions/redis_session_service.py +1 -1
- google_adk_extras/sessions/yaml_file_session_service.py +0 -2
- google_adk_extras/streaming/streaming_controller.py +2 -2
- {google_adk_extras-0.2.6.dist-info → google_adk_extras-0.2.7.dist-info}/METADATA +12 -34
- google_adk_extras-0.2.7.dist-info/RECORD +32 -0
- google_adk_extras/credentials/__init__.py +0 -34
- google_adk_extras/credentials/github_oauth2_credential_service.py +0 -213
- google_adk_extras/credentials/google_oauth2_credential_service.py +0 -216
- google_adk_extras/credentials/http_basic_auth_credential_service.py +0 -388
- google_adk_extras/credentials/jwt_credential_service.py +0 -345
- google_adk_extras/credentials/microsoft_oauth2_credential_service.py +0 -250
- google_adk_extras/credentials/x_oauth2_credential_service.py +0 -240
- google_adk_extras-0.2.6.dist-info/RECORD +0 -39
- {google_adk_extras-0.2.6.dist-info → google_adk_extras-0.2.7.dist-info}/WHEEL +0 -0
- {google_adk_extras-0.2.6.dist-info → google_adk_extras-0.2.7.dist-info}/licenses/LICENSE +0 -0
- {google_adk_extras-0.2.6.dist-info → google_adk_extras-0.2.7.dist-info}/top_level.txt +0 -0
google_adk_extras/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""Production-ready services
|
1
|
+
"""Production-ready services and FastAPI wiring for Google ADK.
|
2
2
|
|
3
3
|
Public API surface:
|
4
4
|
- AdkBuilder
|
@@ -11,7 +11,7 @@ Service groups are exposed via subpackages:
|
|
11
11
|
- google_adk_extras.sessions
|
12
12
|
- google_adk_extras.artifacts
|
13
13
|
- google_adk_extras.memory
|
14
|
-
|
14
|
+
(credential services are provided by ADK; no custom extras here)
|
15
15
|
"""
|
16
16
|
|
17
17
|
from .adk_builder import AdkBuilder
|
@@ -28,4 +28,4 @@ __all__ = [
|
|
28
28
|
"CustomAgentLoader",
|
29
29
|
]
|
30
30
|
|
31
|
-
__version__ = "0.2.
|
31
|
+
__version__ = "0.2.7"
|
google_adk_extras/adk_builder.py
CHANGED
@@ -4,9 +4,7 @@ This module provides the AdkBuilder class that extends Google ADK's FastAPI inte
|
|
4
4
|
with support for custom credential services and enhanced configuration options.
|
5
5
|
"""
|
6
6
|
|
7
|
-
import os
|
8
7
|
import logging
|
9
|
-
from pathlib import Path
|
10
8
|
from typing import Any, Dict, List, Mapping, Optional, Union, Callable
|
11
9
|
from starlette.types import Lifespan
|
12
10
|
|
@@ -15,20 +13,16 @@ from google.adk.runners import Runner
|
|
15
13
|
from google.adk.agents.base_agent import BaseAgent
|
16
14
|
from google.adk.sessions.base_session_service import BaseSessionService
|
17
15
|
from google.adk.sessions.in_memory_session_service import InMemorySessionService
|
18
|
-
from google.adk.sessions.database_session_service import DatabaseSessionService
|
19
16
|
from google.adk.artifacts.base_artifact_service import BaseArtifactService
|
20
17
|
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
|
21
18
|
# GCS removed - vendor specific
|
22
19
|
from google.adk.memory.base_memory_service import BaseMemoryService
|
23
20
|
from google.adk.memory.in_memory_memory_service import InMemoryMemoryService
|
24
21
|
from google.adk.auth.credential_service.base_credential_service import BaseCredentialService
|
25
|
-
from google.adk.auth.credential_service.in_memory_credential_service import InMemoryCredentialService
|
26
22
|
from google.adk.cli.utils.agent_loader import AgentLoader
|
27
23
|
from google.adk.cli.utils.base_agent_loader import BaseAgentLoader
|
28
|
-
from google.adk.cli.adk_web_server import AdkWebServer
|
29
24
|
|
30
25
|
from .custom_agent_loader import CustomAgentLoader
|
31
|
-
from .credentials.base_custom_credential_service import BaseCustomCredentialService
|
32
26
|
|
33
27
|
logger = logging.getLogger(__name__)
|
34
28
|
|
@@ -43,24 +37,19 @@ class AdkBuilder:
|
|
43
37
|
Example:
|
44
38
|
```python
|
45
39
|
from google_adk_extras import AdkBuilder
|
46
|
-
|
40
|
+
# (removed) custom credential service example
|
47
41
|
|
48
42
|
# Build FastAPI app with Google OAuth2 credentials
|
49
43
|
app = (AdkBuilder()
|
50
44
|
.with_agents_dir("./agents")
|
51
45
|
.with_session_service("sqlite:///sessions.db")
|
52
|
-
|
53
|
-
client_id="your-client-id",
|
54
|
-
client_secret="your-secret",
|
55
|
-
scopes=["calendar", "gmail.readonly"]
|
56
|
-
))
|
46
|
+
# credentials: rely on ADK defaults or pass an ADK BaseCredentialService explicitly
|
57
47
|
.with_web_ui()
|
58
48
|
.build_fastapi_app())
|
59
49
|
|
60
50
|
# Or build a Runner directly
|
61
51
|
runner = (AdkBuilder()
|
62
52
|
.with_agents_dir("./agents")
|
63
|
-
.with_credential_service_uri("oauth2-google://client-id:secret@scopes=calendar,gmail.readonly")
|
64
53
|
.build_runner("my_agent"))
|
65
54
|
```
|
66
55
|
"""
|
@@ -75,7 +64,7 @@ class AdkBuilder:
|
|
75
64
|
self._session_service_uri: Optional[str] = None
|
76
65
|
self._artifact_service_uri: Optional[str] = None
|
77
66
|
self._memory_service_uri: Optional[str] = None
|
78
|
-
|
67
|
+
# Note: custom credential-service URI parsing has been removed.
|
79
68
|
self._eval_storage_uri: Optional[str] = None
|
80
69
|
|
81
70
|
# Service instances (alternative to URIs)
|
@@ -190,25 +179,7 @@ class AdkBuilder:
|
|
190
179
|
self._memory_service_uri = uri
|
191
180
|
return self
|
192
181
|
|
193
|
-
|
194
|
-
"""Configure credential service using URI.
|
195
|
-
|
196
|
-
Supported URIs:
|
197
|
-
- "oauth2-google://client-id:secret@scopes=scope1,scope2"
|
198
|
-
- "oauth2-github://client-id:secret@scopes=user,repo"
|
199
|
-
- "oauth2-microsoft://tenant-id/client-id:secret@scopes=User.Read"
|
200
|
-
- "oauth2-x://client-id:secret@scopes=tweet.read,users.read"
|
201
|
-
- "jwt://secret@algorithm=HS256&issuer=my-app&audience=api.example.com&expiration_minutes=60"
|
202
|
-
- "basic-auth://username:password@realm=My API"
|
203
|
-
|
204
|
-
Args:
|
205
|
-
uri: Credential service URI.
|
206
|
-
|
207
|
-
Returns:
|
208
|
-
AdkBuilder: Self for method chaining.
|
209
|
-
"""
|
210
|
-
self._credential_service_uri = uri
|
211
|
-
return self
|
182
|
+
# Removed: URI-based credential service configuration. Use with_credential_service(instance) if needed.
|
212
183
|
|
213
184
|
def with_eval_storage(self, uri: str) -> "AdkBuilder":
|
214
185
|
"""Configure evaluation storage using URI.
|
@@ -606,15 +577,8 @@ class AdkBuilder:
|
|
606
577
|
return InMemoryMemoryService()
|
607
578
|
|
608
579
|
def _create_credential_service(self) -> Optional[BaseCredentialService]:
|
609
|
-
"""
|
610
|
-
|
611
|
-
return self._credential_service
|
612
|
-
|
613
|
-
if self._credential_service_uri:
|
614
|
-
return self._parse_credential_service_uri(self._credential_service_uri)
|
615
|
-
|
616
|
-
# No credential service configured; allow server to default
|
617
|
-
return None
|
580
|
+
"""Return explicitly provided ADK credential service instance (optional)."""
|
581
|
+
return self._credential_service
|
618
582
|
|
619
583
|
def _create_agent_loader(self) -> BaseAgentLoader:
|
620
584
|
"""Create agent loader from configuration.
|
@@ -669,237 +633,19 @@ class AdkBuilder:
|
|
669
633
|
"or with_agent_loader() to configure agents."
|
670
634
|
)
|
671
635
|
|
672
|
-
|
673
|
-
"""Parse credential service URI and create appropriate service.
|
674
|
-
|
675
|
-
Args:
|
676
|
-
uri: Credential service URI.
|
677
|
-
|
678
|
-
Returns:
|
679
|
-
BaseCredentialService: Configured credential service.
|
680
|
-
|
681
|
-
Raises:
|
682
|
-
ValueError: If URI format is invalid or unsupported.
|
683
|
-
"""
|
684
|
-
try:
|
685
|
-
if uri.startswith("oauth2-google://"):
|
686
|
-
return self._parse_google_oauth2_uri(uri)
|
687
|
-
elif uri.startswith("oauth2-github://"):
|
688
|
-
return self._parse_github_oauth2_uri(uri)
|
689
|
-
elif uri.startswith("oauth2-microsoft://"):
|
690
|
-
return self._parse_microsoft_oauth2_uri(uri)
|
691
|
-
elif uri.startswith("oauth2-x://"):
|
692
|
-
return self._parse_x_oauth2_uri(uri)
|
693
|
-
elif uri.startswith("jwt://"):
|
694
|
-
return self._parse_jwt_uri(uri)
|
695
|
-
elif uri.startswith("basic-auth://"):
|
696
|
-
return self._parse_basic_auth_uri(uri)
|
697
|
-
else:
|
698
|
-
raise ValueError(f"Unsupported credential service URI scheme: {uri}")
|
699
|
-
except Exception as e:
|
700
|
-
raise ValueError(f"Failed to parse credential service URI '{uri}': {e}")
|
636
|
+
# Removed: all URI-based credential parsing helpers for credentials.
|
701
637
|
|
702
|
-
|
703
|
-
"""Parse Google OAuth2 URI: oauth2-google://client-id:secret@scopes=scope1,scope2"""
|
704
|
-
from .credentials.google_oauth2_credential_service import (
|
705
|
-
GoogleOAuth2CredentialService,
|
706
|
-
)
|
707
|
-
# Remove scheme
|
708
|
-
uri_part = uri[len("oauth2-google://"):]
|
709
|
-
|
710
|
-
# Split at @
|
711
|
-
if "@" in uri_part:
|
712
|
-
credentials_part, params_part = uri_part.split("@", 1)
|
713
|
-
else:
|
714
|
-
credentials_part = uri_part
|
715
|
-
params_part = ""
|
716
|
-
|
717
|
-
# Parse credentials
|
718
|
-
if ":" in credentials_part:
|
719
|
-
client_id, client_secret = credentials_part.split(":", 1)
|
720
|
-
else:
|
721
|
-
raise ValueError("Google OAuth2 URI must include client_id:client_secret")
|
722
|
-
|
723
|
-
# Parse parameters
|
724
|
-
scopes = []
|
725
|
-
if params_part:
|
726
|
-
for param in params_part.split("&"):
|
727
|
-
if param.startswith("scopes="):
|
728
|
-
scopes = param[7:].split(",")
|
729
|
-
|
730
|
-
return GoogleOAuth2CredentialService(
|
731
|
-
client_id=client_id,
|
732
|
-
client_secret=client_secret,
|
733
|
-
scopes=scopes or ["openid", "email", "profile"]
|
734
|
-
)
|
638
|
+
# (removed) _parse_google_oauth2_uri
|
735
639
|
|
736
|
-
|
737
|
-
"""Parse GitHub OAuth2 URI: oauth2-github://client-id:secret@scopes=user,repo"""
|
738
|
-
from .credentials.github_oauth2_credential_service import (
|
739
|
-
GitHubOAuth2CredentialService,
|
740
|
-
)
|
741
|
-
uri_part = uri[len("oauth2-github://"):]
|
742
|
-
|
743
|
-
if "@" in uri_part:
|
744
|
-
credentials_part, params_part = uri_part.split("@", 1)
|
745
|
-
else:
|
746
|
-
credentials_part = uri_part
|
747
|
-
params_part = ""
|
748
|
-
|
749
|
-
if ":" in credentials_part:
|
750
|
-
client_id, client_secret = credentials_part.split(":", 1)
|
751
|
-
else:
|
752
|
-
raise ValueError("GitHub OAuth2 URI must include client_id:client_secret")
|
753
|
-
|
754
|
-
scopes = []
|
755
|
-
if params_part:
|
756
|
-
for param in params_part.split("&"):
|
757
|
-
if param.startswith("scopes="):
|
758
|
-
scopes = param[7:].split(",")
|
759
|
-
|
760
|
-
return GitHubOAuth2CredentialService(
|
761
|
-
client_id=client_id,
|
762
|
-
client_secret=client_secret,
|
763
|
-
scopes=scopes or ["user"]
|
764
|
-
)
|
640
|
+
# (removed) _parse_github_oauth2_uri
|
765
641
|
|
766
|
-
|
767
|
-
"""Parse Microsoft OAuth2 URI: oauth2-microsoft://tenant-id/client-id:secret@scopes=User.Read"""
|
768
|
-
from .credentials.microsoft_oauth2_credential_service import (
|
769
|
-
MicrosoftOAuth2CredentialService,
|
770
|
-
)
|
771
|
-
uri_part = uri[len("oauth2-microsoft://"):]
|
772
|
-
|
773
|
-
if "@" in uri_part:
|
774
|
-
credentials_part, params_part = uri_part.split("@", 1)
|
775
|
-
else:
|
776
|
-
credentials_part = uri_part
|
777
|
-
params_part = ""
|
778
|
-
|
779
|
-
# Parse tenant_id/client_id:secret
|
780
|
-
if "/" in credentials_part:
|
781
|
-
tenant_part, client_part = credentials_part.split("/", 1)
|
782
|
-
else:
|
783
|
-
raise ValueError("Microsoft OAuth2 URI must include tenant-id/client-id:secret")
|
784
|
-
|
785
|
-
if ":" in client_part:
|
786
|
-
client_id, client_secret = client_part.split(":", 1)
|
787
|
-
else:
|
788
|
-
raise ValueError("Microsoft OAuth2 URI must include client_id:client_secret")
|
789
|
-
|
790
|
-
scopes = []
|
791
|
-
if params_part:
|
792
|
-
for param in params_part.split("&"):
|
793
|
-
if param.startswith("scopes="):
|
794
|
-
scopes = param[7:].split(",")
|
795
|
-
|
796
|
-
return MicrosoftOAuth2CredentialService(
|
797
|
-
tenant_id=tenant_part,
|
798
|
-
client_id=client_id,
|
799
|
-
client_secret=client_secret,
|
800
|
-
scopes=scopes or ["User.Read"]
|
801
|
-
)
|
642
|
+
# (removed) _parse_microsoft_oauth2_uri
|
802
643
|
|
803
|
-
|
804
|
-
"""Parse X OAuth2 URI: oauth2-x://client-id:secret@scopes=tweet.read,users.read"""
|
805
|
-
from .credentials.x_oauth2_credential_service import XOAuth2CredentialService
|
806
|
-
uri_part = uri[len("oauth2-x://"):]
|
807
|
-
|
808
|
-
if "@" in uri_part:
|
809
|
-
credentials_part, params_part = uri_part.split("@", 1)
|
810
|
-
else:
|
811
|
-
credentials_part = uri_part
|
812
|
-
params_part = ""
|
813
|
-
|
814
|
-
if ":" in credentials_part:
|
815
|
-
client_id, client_secret = credentials_part.split(":", 1)
|
816
|
-
else:
|
817
|
-
raise ValueError("X OAuth2 URI must include client_id:client_secret")
|
818
|
-
|
819
|
-
scopes = []
|
820
|
-
if params_part:
|
821
|
-
for param in params_part.split("&"):
|
822
|
-
if param.startswith("scopes="):
|
823
|
-
scopes = param[7:].split(",")
|
824
|
-
|
825
|
-
return XOAuth2CredentialService(
|
826
|
-
client_id=client_id,
|
827
|
-
client_secret=client_secret,
|
828
|
-
scopes=scopes or ["tweet.read", "users.read", "offline.access"]
|
829
|
-
)
|
644
|
+
# (removed) _parse_x_oauth2_uri
|
830
645
|
|
831
|
-
|
832
|
-
"""Parse JWT URI: jwt://secret@algorithm=HS256&issuer=my-app&audience=api.example.com&expiration_minutes=60"""
|
833
|
-
from .credentials.jwt_credential_service import JWTCredentialService
|
834
|
-
uri_part = uri[len("jwt://"):]
|
835
|
-
|
836
|
-
if "@" in uri_part:
|
837
|
-
secret, params_part = uri_part.split("@", 1)
|
838
|
-
else:
|
839
|
-
secret = uri_part
|
840
|
-
params_part = ""
|
841
|
-
|
842
|
-
# Parse parameters
|
843
|
-
algorithm = "HS256"
|
844
|
-
issuer = None
|
845
|
-
audience = None
|
846
|
-
expiration_minutes = 60
|
847
|
-
custom_claims = {}
|
848
|
-
|
849
|
-
if params_part:
|
850
|
-
for param in params_part.split("&"):
|
851
|
-
if "=" in param:
|
852
|
-
key, value = param.split("=", 1)
|
853
|
-
if key == "algorithm":
|
854
|
-
algorithm = value
|
855
|
-
elif key == "issuer":
|
856
|
-
issuer = value
|
857
|
-
elif key == "audience":
|
858
|
-
audience = value
|
859
|
-
elif key == "expiration_minutes":
|
860
|
-
expiration_minutes = int(value)
|
861
|
-
else:
|
862
|
-
# Custom claim
|
863
|
-
custom_claims[key] = value
|
864
|
-
|
865
|
-
return JWTCredentialService(
|
866
|
-
secret=secret,
|
867
|
-
algorithm=algorithm,
|
868
|
-
issuer=issuer,
|
869
|
-
audience=audience,
|
870
|
-
expiration_minutes=expiration_minutes,
|
871
|
-
custom_claims=custom_claims
|
872
|
-
)
|
646
|
+
# (removed) _parse_jwt_uri
|
873
647
|
|
874
|
-
|
875
|
-
"""Parse Basic Auth URI: basic-auth://username:password@realm=My API"""
|
876
|
-
from .credentials.http_basic_auth_credential_service import (
|
877
|
-
HTTPBasicAuthCredentialService,
|
878
|
-
)
|
879
|
-
uri_part = uri[len("basic-auth://"):]
|
880
|
-
|
881
|
-
if "@" in uri_part:
|
882
|
-
credentials_part, params_part = uri_part.split("@", 1)
|
883
|
-
else:
|
884
|
-
credentials_part = uri_part
|
885
|
-
params_part = ""
|
886
|
-
|
887
|
-
if ":" in credentials_part:
|
888
|
-
username, password = credentials_part.split(":", 1)
|
889
|
-
else:
|
890
|
-
raise ValueError("Basic Auth URI must include username:password")
|
891
|
-
|
892
|
-
realm = None
|
893
|
-
if params_part:
|
894
|
-
for param in params_part.split("&"):
|
895
|
-
if param.startswith("realm="):
|
896
|
-
realm = param[6:]
|
897
|
-
|
898
|
-
return HTTPBasicAuthCredentialService(
|
899
|
-
username=username,
|
900
|
-
password=password,
|
901
|
-
realm=realm
|
902
|
-
)
|
648
|
+
# (removed) _parse_basic_auth_uri
|
903
649
|
|
904
650
|
# Build methods
|
905
651
|
def build_fastapi_app(self) -> FastAPI:
|
@@ -918,20 +664,7 @@ class AdkBuilder:
|
|
918
664
|
memory_service = self._create_memory_service()
|
919
665
|
credential_service = self._create_credential_service()
|
920
666
|
|
921
|
-
#
|
922
|
-
if isinstance(credential_service, BaseCustomCredentialService):
|
923
|
-
import asyncio
|
924
|
-
try:
|
925
|
-
# Try to initialize in current event loop
|
926
|
-
loop = asyncio.get_event_loop()
|
927
|
-
if loop.is_running():
|
928
|
-
# Create a task for initialization
|
929
|
-
asyncio.create_task(credential_service.initialize())
|
930
|
-
else:
|
931
|
-
loop.run_until_complete(credential_service.initialize())
|
932
|
-
except RuntimeError:
|
933
|
-
# No event loop, create one
|
934
|
-
asyncio.run(credential_service.initialize())
|
667
|
+
# No custom credential initialization; ADK services are passed through
|
935
668
|
|
936
669
|
# Use our enhanced FastAPI function that properly supports credential services
|
937
670
|
logger.info("Building FastAPI app with enhanced credential service support")
|
@@ -1005,17 +738,7 @@ class AdkBuilder:
|
|
1005
738
|
memory_service = self._create_memory_service()
|
1006
739
|
credential_service = self._create_credential_service()
|
1007
740
|
|
1008
|
-
#
|
1009
|
-
if isinstance(credential_service, BaseCustomCredentialService):
|
1010
|
-
import asyncio
|
1011
|
-
try:
|
1012
|
-
loop = asyncio.get_event_loop()
|
1013
|
-
if loop.is_running():
|
1014
|
-
asyncio.create_task(credential_service.initialize())
|
1015
|
-
else:
|
1016
|
-
loop.run_until_complete(credential_service.initialize())
|
1017
|
-
except RuntimeError:
|
1018
|
-
asyncio.run(credential_service.initialize())
|
741
|
+
# No custom credential initialization; ADK services are passed through
|
1019
742
|
|
1020
743
|
# Create Runner with all services
|
1021
744
|
app_name = self._app_name or (agent_or_agent_name if isinstance(agent_or_agent_name, str) else "default_app")
|
@@ -7,7 +7,7 @@ thread-safe registry management.
|
|
7
7
|
|
8
8
|
import logging
|
9
9
|
import threading
|
10
|
-
from typing import Dict, List
|
10
|
+
from typing import Dict, List
|
11
11
|
|
12
12
|
from google.adk.agents.base_agent import BaseAgent
|
13
13
|
from google.adk.cli.utils.base_agent_loader import BaseAgentLoader
|
@@ -5,13 +5,11 @@ AdkWebServer to use our EnhancedRunner with advanced features.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import os
|
8
|
-
from typing import Optional
|
9
8
|
|
10
9
|
from google.adk.cli.adk_web_server import AdkWebServer
|
11
10
|
from google.adk.auth.credential_service.in_memory_credential_service import InMemoryCredentialService
|
12
11
|
from google.adk.cli.utils import cleanup
|
13
12
|
from google.adk.cli.utils import envs
|
14
|
-
from google.adk.runners import Runner
|
15
13
|
|
16
14
|
from .enhanced_runner import EnhancedRunner
|
17
15
|
|
@@ -22,7 +22,6 @@ from watchdog.observers import Observer
|
|
22
22
|
|
23
23
|
from google.adk.artifacts.gcs_artifact_service import GcsArtifactService
|
24
24
|
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
|
25
|
-
from google.adk.auth.credential_service.in_memory_credential_service import InMemoryCredentialService
|
26
25
|
from google.adk.auth.credential_service.base_credential_service import BaseCredentialService
|
27
26
|
from google.adk.evaluation.local_eval_set_results_manager import LocalEvalSetResultsManager
|
28
27
|
from google.adk.evaluation.local_eval_sets_manager import LocalEvalSetsManager
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import asyncio
|
2
2
|
import time
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import Any, Dict, Optional,
|
4
|
+
from typing import Any, Dict, Optional, Callable, Awaitable
|
5
5
|
|
6
|
-
from fastapi import
|
6
|
+
from fastapi import HTTPException
|
7
7
|
from pydantic import BaseModel
|
8
8
|
|
9
9
|
from google.adk.events.event import Event
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: google-adk-extras
|
3
|
-
Version: 0.2.
|
4
|
-
Summary: Production-ready services
|
3
|
+
Version: 0.2.7
|
4
|
+
Summary: Production-ready services and FastAPI wiring for Google ADK
|
5
5
|
Home-page: https://github.com/DeadMeme5441/google-adk-extras
|
6
6
|
Author: DeadMeme5441
|
7
7
|
Author-email: DeadMeme5441 <deadunderscorememe@gmail.com>
|
@@ -49,7 +49,7 @@ Dynamic: requires-python
|
|
49
49
|
[](https://deadmeme5441.github.io/google-adk-extras/)
|
50
50
|
[](https://github.com/DeadMeme5441/google-adk-extras/actions/workflows/docs.yml)
|
51
51
|
|
52
|
-
Production-ready extensions for Google ADK (Agent Development Kit). This library adds durable service backends (sessions, artifacts, memory)
|
52
|
+
Production-ready extensions for Google ADK (Agent Development Kit). This library adds durable service backends (sessions, artifacts, memory) and clean FastAPI wiring (with optional streaming) so you can run ADK agents with real storage.
|
53
53
|
|
54
54
|
What this is not: a fork of ADK. It builds on ADK’s core runtime, agents, tools and callbacks, and drops in where ADK expects services and a web server.
|
55
55
|
|
@@ -58,10 +58,9 @@ What this is not: a fork of ADK. It builds on ADK’s core runtime, agents, tool
|
|
58
58
|
|
59
59
|
ADK provides the core primitives (Runner, Session/State, MemoryService, ArtifactService, CredentialService, Agents/Tools, callbacks, Dev UI, and deployment paths). See the official ADK docs for concepts and APIs.
|
60
60
|
|
61
|
-
This package focuses on
|
61
|
+
This package focuses on a few gaps common in real apps:
|
62
62
|
- Durable storage backends beyond in‑memory defaults
|
63
|
-
-
|
64
|
-
- FastAPI integration that accepts your credential service without hacks
|
63
|
+
- FastAPI integration with optional streaming (SSE/WS)
|
65
64
|
|
66
65
|
|
67
66
|
## Features
|
@@ -69,8 +68,7 @@ This package focuses on three gaps common in real apps:
|
|
69
68
|
- Session services: SQL (SQLite/Postgres/MySQL), MongoDB, Redis, YAML files
|
70
69
|
- Artifact services: Local folder (versioned), S3‑compatible, SQL, MongoDB
|
71
70
|
- Memory services: SQL, MongoDB, Redis, YAML files (term search over text parts)
|
72
|
-
-
|
73
|
-
- Enhanced FastAPI wiring that respects a provided credential service
|
71
|
+
- Enhanced FastAPI wiring for ADK apps (with optional streaming)
|
74
72
|
- Fluent builder (`AdkBuilder`) to assemble a FastAPI app or a Runner
|
75
73
|
- A2A helpers for exposing/consuming agents (see below)
|
76
74
|
|
@@ -95,17 +93,17 @@ If you plan to use specific backends, also install their clients (examples):
|
|
95
93
|
- MongoDB: `uv pip install pymongo`
|
96
94
|
- Redis: `uv pip install redis`
|
97
95
|
- S3: `uv pip install boto3`
|
98
|
-
|
96
|
+
|
97
|
+
Note on credentials (0.2.7): This release removes custom credential services and URI helpers from this package. For outbound credentials used by tools, rely on ADK’s experimental BaseCredentialService (e.g., InMemory/SessionState) or your own ADK-compatible implementation. Inbound API authentication (protecting /run and streaming routes) will be provided as an optional FastAPI layer separately.
|
99
98
|
|
100
99
|
|
101
100
|
## Quickstart (FastAPI)
|
102
101
|
|
103
|
-
Use the fluent builder to wire services
|
102
|
+
Use the fluent builder to wire services. Then run with uvicorn.
|
104
103
|
|
105
104
|
```python
|
106
105
|
# app.py
|
107
106
|
from google_adk_extras import AdkBuilder
|
108
|
-
from google_adk_extras.credentials import GoogleOAuth2CredentialService
|
109
107
|
|
110
108
|
app = (
|
111
109
|
AdkBuilder()
|
@@ -113,11 +111,7 @@ app = (
|
|
113
111
|
.with_session_service("sqlite:///./sessions.db") # or: mongodb://, redis://, yaml://
|
114
112
|
.with_artifact_service("local://./artifacts") # or: s3://bucket, mongodb://, sql://
|
115
113
|
.with_memory_service("yaml://./memory") # or: redis://, mongodb://, sql://
|
116
|
-
|
117
|
-
client_id="…apps.googleusercontent.com",
|
118
|
-
client_secret="…",
|
119
|
-
scopes=["openid", "email", "profile"],
|
120
|
-
))
|
114
|
+
# credentials: rely on ADK defaults or pass an ADK BaseCredentialService if needed
|
121
115
|
.with_web_ui(True) # serve ADK’s dev UI if assets available
|
122
116
|
.with_agent_reload(True)
|
123
117
|
.build_fastapi_app()
|
@@ -251,24 +245,8 @@ app = (
|
|
251
245
|
```
|
252
246
|
|
253
247
|
|
254
|
-
|
255
|
-
|
256
|
-
If you prefer URIs instead of constructing services:
|
257
|
-
|
258
|
-
- Google OAuth2: `oauth2-google://client_id:secret@scopes=openid,email,profile`
|
259
|
-
- GitHub OAuth2: `oauth2-github://client_id:secret@scopes=user,repo`
|
260
|
-
- Microsoft OAuth2: `oauth2-microsoft://<tenant>/<client_id>:<secret>@scopes=User.Read`
|
261
|
-
- X OAuth2: `oauth2-x://client_id:secret@scopes=tweet.read,users.read`
|
262
|
-
- JWT: `jwt://<secret>@algorithm=HS256&issuer=my-app&audience=api.example.com&expiration_minutes=60`
|
263
|
-
- Basic: `basic-auth://username:password@realm=My%20API`
|
264
|
-
|
265
|
-
```python
|
266
|
-
cred = (
|
267
|
-
AdkBuilder()
|
268
|
-
.with_credential_service_uri("jwt://secret@issuer=my-app")
|
269
|
-
._create_credential_service()
|
270
|
-
)
|
271
|
-
```
|
248
|
+
<!-- Credential URI helpers removed. Use ADK’s BaseCredentialService directly if needed,
|
249
|
+
and handle inbound API authentication at FastAPI level. -->
|
272
250
|
|
273
251
|
|
274
252
|
## Notes & limitations
|