google-adk-extras 0.1.1__py3-none-any.whl → 0.2.5__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.
Files changed (35) hide show
  1. google_adk_extras/__init__.py +31 -1
  2. google_adk_extras/adk_builder.py +1030 -0
  3. google_adk_extras/artifacts/__init__.py +25 -12
  4. google_adk_extras/artifacts/base_custom_artifact_service.py +148 -11
  5. google_adk_extras/artifacts/local_folder_artifact_service.py +133 -13
  6. google_adk_extras/artifacts/s3_artifact_service.py +135 -19
  7. google_adk_extras/artifacts/sql_artifact_service.py +109 -10
  8. google_adk_extras/credentials/__init__.py +34 -0
  9. google_adk_extras/credentials/base_custom_credential_service.py +113 -0
  10. google_adk_extras/credentials/github_oauth2_credential_service.py +213 -0
  11. google_adk_extras/credentials/google_oauth2_credential_service.py +216 -0
  12. google_adk_extras/credentials/http_basic_auth_credential_service.py +388 -0
  13. google_adk_extras/credentials/jwt_credential_service.py +345 -0
  14. google_adk_extras/credentials/microsoft_oauth2_credential_service.py +250 -0
  15. google_adk_extras/credentials/x_oauth2_credential_service.py +240 -0
  16. google_adk_extras/custom_agent_loader.py +170 -0
  17. google_adk_extras/enhanced_adk_web_server.py +137 -0
  18. google_adk_extras/enhanced_fastapi.py +507 -0
  19. google_adk_extras/enhanced_runner.py +38 -0
  20. google_adk_extras/memory/__init__.py +30 -13
  21. google_adk_extras/memory/base_custom_memory_service.py +37 -5
  22. google_adk_extras/memory/sql_memory_service.py +105 -19
  23. google_adk_extras/memory/yaml_file_memory_service.py +115 -22
  24. google_adk_extras/sessions/__init__.py +29 -13
  25. google_adk_extras/sessions/base_custom_session_service.py +133 -11
  26. google_adk_extras/sessions/sql_session_service.py +127 -16
  27. google_adk_extras/sessions/yaml_file_session_service.py +122 -14
  28. google_adk_extras-0.2.5.dist-info/METADATA +302 -0
  29. google_adk_extras-0.2.5.dist-info/RECORD +37 -0
  30. google_adk_extras/py.typed +0 -0
  31. google_adk_extras-0.1.1.dist-info/METADATA +0 -175
  32. google_adk_extras-0.1.1.dist-info/RECORD +0 -25
  33. {google_adk_extras-0.1.1.dist-info → google_adk_extras-0.2.5.dist-info}/WHEEL +0 -0
  34. {google_adk_extras-0.1.1.dist-info → google_adk_extras-0.2.5.dist-info}/licenses/LICENSE +0 -0
  35. {google_adk_extras-0.1.1.dist-info → google_adk_extras-0.2.5.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,28 @@
1
- """Custom artifact service implementations for Google ADK."""
1
+ """Custom artifact service implementations for Google ADK.
2
+
3
+ Optional backends are imported lazily based on installed dependencies.
4
+ """
2
5
 
3
6
  from .base_custom_artifact_service import BaseCustomArtifactService
4
- from .sql_artifact_service import SQLArtifactService
5
- from .mongo_artifact_service import MongoArtifactService
7
+
8
+ try:
9
+ from .sql_artifact_service import SQLArtifactService # type: ignore
10
+ except Exception:
11
+ SQLArtifactService = None # type: ignore
12
+
13
+ try:
14
+ from .mongo_artifact_service import MongoArtifactService # type: ignore
15
+ except Exception:
16
+ MongoArtifactService = None # type: ignore
17
+
6
18
  from .local_folder_artifact_service import LocalFolderArtifactService
7
- from .s3_artifact_service import S3ArtifactService
8
-
9
- __all__ = [
10
- "BaseCustomArtifactService",
11
- "SQLArtifactService",
12
- "MongoArtifactService",
13
- "LocalFolderArtifactService",
14
- "S3ArtifactService",
15
- ]
19
+
20
+ try:
21
+ from .s3_artifact_service import S3ArtifactService # type: ignore
22
+ except Exception:
23
+ S3ArtifactService = None # type: ignore
24
+
25
+ __all__ = ["BaseCustomArtifactService", "LocalFolderArtifactService"]
26
+ for _name in ("SQLArtifactService", "MongoArtifactService", "S3ArtifactService"):
27
+ if globals().get(_name) is not None:
28
+ __all__.append(_name)
@@ -8,7 +8,11 @@ from google.genai import types
8
8
 
9
9
 
10
10
  class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
11
- """Base class for custom artifact services with common functionality."""
11
+ """Base class for custom artifact services with common functionality.
12
+
13
+ This abstract base class provides a foundation for implementing custom
14
+ artifact services with automatic initialization and cleanup handling.
15
+ """
12
16
 
13
17
  def __init__(self):
14
18
  """Initialize the base custom artifact service."""
@@ -20,6 +24,9 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
20
24
 
21
25
  This method should be called before using the service to ensure
22
26
  any required setup (database connections, etc.) is complete.
27
+
28
+ Raises:
29
+ RuntimeError: If initialization fails.
23
30
  """
24
31
  if not self._initialized:
25
32
  await self._initialize_impl()
@@ -31,6 +38,9 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
31
38
 
32
39
  This method should handle any setup required for the service to function,
33
40
  such as database connections, creating tables, directories, etc.
41
+
42
+ Raises:
43
+ RuntimeError: If initialization fails.
34
44
  """
35
45
  pass
36
46
 
@@ -62,7 +72,21 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
62
72
  filename: str,
63
73
  artifact: types.Part,
64
74
  ) -> int:
65
- """Save an artifact."""
75
+ """Save an artifact.
76
+
77
+ Args:
78
+ app_name: The name of the application.
79
+ user_id: The ID of the user.
80
+ session_id: The ID of the session.
81
+ filename: The name of the file to save.
82
+ artifact: The artifact to save.
83
+
84
+ Returns:
85
+ The version number of the saved artifact.
86
+
87
+ Raises:
88
+ RuntimeError: If saving the artifact fails.
89
+ """
66
90
  if not self._initialized:
67
91
  await self.initialize()
68
92
  return await self._save_artifact_impl(
@@ -82,7 +106,22 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
82
106
  filename: str,
83
107
  version: Optional[int] = None,
84
108
  ) -> Optional[types.Part]:
85
- """Load an artifact."""
109
+ """Load an artifact.
110
+
111
+ Args:
112
+ app_name: The name of the application.
113
+ user_id: The ID of the user.
114
+ session_id: The ID of the session.
115
+ filename: The name of the file to load.
116
+ version: Optional version number to load. If not provided,
117
+ the latest version will be loaded.
118
+
119
+ Returns:
120
+ The loaded artifact if found, None otherwise.
121
+
122
+ Raises:
123
+ RuntimeError: If loading the artifact fails.
124
+ """
86
125
  if not self._initialized:
87
126
  await self.initialize()
88
127
  return await self._load_artifact_impl(
@@ -100,7 +139,19 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
100
139
  user_id: str,
101
140
  session_id: str,
102
141
  ) -> List[str]:
103
- """List artifact keys."""
142
+ """List artifact keys.
143
+
144
+ Args:
145
+ app_name: The name of the application.
146
+ user_id: The ID of the user.
147
+ session_id: The ID of the session.
148
+
149
+ Returns:
150
+ A list of artifact keys (filenames).
151
+
152
+ Raises:
153
+ RuntimeError: If listing artifact keys fails.
154
+ """
104
155
  if not self._initialized:
105
156
  await self.initialize()
106
157
  return await self._list_artifact_keys_impl(
@@ -117,7 +168,17 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
117
168
  session_id: str,
118
169
  filename: str,
119
170
  ) -> None:
120
- """Delete an artifact."""
171
+ """Delete an artifact.
172
+
173
+ Args:
174
+ app_name: The name of the application.
175
+ user_id: The ID of the user.
176
+ session_id: The ID of the session.
177
+ filename: The name of the file to delete.
178
+
179
+ Raises:
180
+ RuntimeError: If deleting the artifact fails.
181
+ """
121
182
  if not self._initialized:
122
183
  await self.initialize()
123
184
  await self._delete_artifact_impl(
@@ -135,7 +196,20 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
135
196
  session_id: str,
136
197
  filename: str,
137
198
  ) -> List[int]:
138
- """List versions of an artifact."""
199
+ """List versions of an artifact.
200
+
201
+ Args:
202
+ app_name: The name of the application.
203
+ user_id: The ID of the user.
204
+ session_id: The ID of the session.
205
+ filename: The name of the file to list versions for.
206
+
207
+ Returns:
208
+ A list of version numbers.
209
+
210
+ Raises:
211
+ RuntimeError: If listing versions fails.
212
+ """
139
213
  if not self._initialized:
140
214
  await self.initialize()
141
215
  return await self._list_versions_impl(
@@ -155,7 +229,21 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
155
229
  filename: str,
156
230
  artifact: types.Part,
157
231
  ) -> int:
158
- """Implementation of artifact saving."""
232
+ """Implementation of artifact saving.
233
+
234
+ Args:
235
+ app_name: The name of the application.
236
+ user_id: The ID of the user.
237
+ session_id: The ID of the session.
238
+ filename: The name of the file to save.
239
+ artifact: The artifact to save.
240
+
241
+ Returns:
242
+ The version number of the saved artifact.
243
+
244
+ Raises:
245
+ RuntimeError: If saving the artifact fails.
246
+ """
159
247
  pass
160
248
 
161
249
  @abc.abstractmethod
@@ -168,7 +256,21 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
168
256
  filename: str,
169
257
  version: Optional[int] = None,
170
258
  ) -> Optional[types.Part]:
171
- """Implementation of artifact loading."""
259
+ """Implementation of artifact loading.
260
+
261
+ Args:
262
+ app_name: The name of the application.
263
+ user_id: The ID of the user.
264
+ session_id: The ID of the session.
265
+ filename: The name of the file to load.
266
+ version: Optional version number to load.
267
+
268
+ Returns:
269
+ The loaded artifact if found, None otherwise.
270
+
271
+ Raises:
272
+ RuntimeError: If loading the artifact fails.
273
+ """
172
274
  pass
173
275
 
174
276
  @abc.abstractmethod
@@ -179,7 +281,19 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
179
281
  user_id: str,
180
282
  session_id: str,
181
283
  ) -> List[str]:
182
- """Implementation of artifact key listing."""
284
+ """Implementation of artifact key listing.
285
+
286
+ Args:
287
+ app_name: The name of the application.
288
+ user_id: The ID of the user.
289
+ session_id: The ID of the session.
290
+
291
+ Returns:
292
+ A list of artifact keys (filenames).
293
+
294
+ Raises:
295
+ RuntimeError: If listing artifact keys fails.
296
+ """
183
297
  pass
184
298
 
185
299
  @abc.abstractmethod
@@ -191,7 +305,17 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
191
305
  session_id: str,
192
306
  filename: str,
193
307
  ) -> None:
194
- """Implementation of artifact deletion."""
308
+ """Implementation of artifact deletion.
309
+
310
+ Args:
311
+ app_name: The name of the application.
312
+ user_id: The ID of the user.
313
+ session_id: The ID of the session.
314
+ filename: The name of the file to delete.
315
+
316
+ Raises:
317
+ RuntimeError: If deleting the artifact fails.
318
+ """
195
319
  pass
196
320
 
197
321
  @abc.abstractmethod
@@ -203,5 +327,18 @@ class BaseCustomArtifactService(BaseArtifactService, abc.ABC):
203
327
  session_id: str,
204
328
  filename: str,
205
329
  ) -> List[int]:
206
- """Implementation of version listing."""
330
+ """Implementation of version listing.
331
+
332
+ Args:
333
+ app_name: The name of the application.
334
+ user_id: The ID of the user.
335
+ session_id: The ID of the session.
336
+ filename: The name of the file to list versions for.
337
+
338
+ Returns:
339
+ A list of version numbers.
340
+
341
+ Raises:
342
+ RuntimeError: If listing versions fails.
343
+ """
207
344
  pass
@@ -12,13 +12,17 @@ from .base_custom_artifact_service import BaseCustomArtifactService
12
12
 
13
13
 
14
14
  class LocalFolderArtifactService(BaseCustomArtifactService):
15
- """Local folder-based artifact service implementation."""
15
+ """Local folder-based artifact service implementation.
16
+
17
+ This service stores artifacts in the local file system with full versioning support.
18
+ Each artifact is stored with its metadata in JSON format and binary data in separate files.
19
+ """
16
20
 
17
21
  def __init__(self, base_directory: str = "./artifacts"):
18
22
  """Initialize the local folder artifact service.
19
23
 
20
24
  Args:
21
- base_directory: Base directory for storing artifacts
25
+ base_directory: Base directory for storing artifacts. Defaults to "./artifacts".
22
26
  """
23
27
  super().__init__()
24
28
  self.base_directory = Path(base_directory)
@@ -26,7 +30,10 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
26
30
  self.base_directory.mkdir(parents=True, exist_ok=True)
27
31
 
28
32
  async def _initialize_impl(self) -> None:
29
- """Initialize the file system artifact service."""
33
+ """Initialize the file system artifact service.
34
+
35
+ Ensures the base directory exists.
36
+ """
30
37
  # Ensure base directory exists
31
38
  self.base_directory.mkdir(parents=True, exist_ok=True)
32
39
 
@@ -35,30 +42,78 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
35
42
  pass
36
43
 
37
44
  def _get_artifact_directory(self, app_name: str, user_id: str, session_id: str) -> Path:
38
- """Generate directory path for artifacts."""
45
+ """Generate directory path for artifacts.
46
+
47
+ Args:
48
+ app_name: The name of the application.
49
+ user_id: The ID of the user.
50
+ session_id: The ID of the session.
51
+
52
+ Returns:
53
+ Path to the artifact directory.
54
+ """
39
55
  directory = self.base_directory / app_name / user_id / session_id
40
56
  directory.mkdir(parents=True, exist_ok=True)
41
57
  return directory
42
58
 
43
59
  def _get_artifact_file_path(self, app_name: str, user_id: str, session_id: str, filename: str) -> Path:
44
- """Generate file path for artifact metadata."""
60
+ """Generate file path for artifact metadata.
61
+
62
+ Args:
63
+ app_name: The name of the application.
64
+ user_id: The ID of the user.
65
+ session_id: The ID of the session.
66
+ filename: The name of the file.
67
+
68
+ Returns:
69
+ Path to the metadata file.
70
+ """
45
71
  directory = self._get_artifact_directory(app_name, user_id, session_id)
46
72
  return directory / f"{filename}.json"
47
73
 
48
74
  def _get_artifact_data_path(self, app_name: str, user_id: str, session_id: str, filename: str, version: int) -> Path:
49
- """Generate file path for artifact data."""
75
+ """Generate file path for artifact data.
76
+
77
+ Args:
78
+ app_name: The name of the application.
79
+ user_id: The ID of the user.
80
+ session_id: The ID of the session.
81
+ filename: The name of the file.
82
+ version: The version number.
83
+
84
+ Returns:
85
+ Path to the data file.
86
+ """
50
87
  directory = self._get_artifact_directory(app_name, user_id, session_id)
51
88
  return directory / f"{filename}.v{version}.data"
52
89
 
53
90
  def _serialize_blob(self, part: types.Part) -> tuple[bytes, str]:
54
- """Extract blob data and mime type from a Part."""
91
+ """Extract blob data and mime type from a Part.
92
+
93
+ Args:
94
+ part: The Part object containing the blob data.
95
+
96
+ Returns:
97
+ A tuple of (data, mime_type).
98
+
99
+ Raises:
100
+ ValueError: If the part type is not supported.
101
+ """
55
102
  if part.inline_data:
56
103
  return part.inline_data.data, part.inline_data.mime_type or "application/octet-stream"
57
104
  else:
58
105
  raise ValueError("Only inline_data parts are supported")
59
106
 
60
107
  def _deserialize_blob(self, data: bytes, mime_type: str) -> types.Part:
61
- """Create a Part from blob data and mime type."""
108
+ """Create a Part from blob data and mime type.
109
+
110
+ Args:
111
+ data: The binary data.
112
+ mime_type: The MIME type of the data.
113
+
114
+ Returns:
115
+ A Part object containing the blob data.
116
+ """
62
117
  blob = types.Blob(data=data, mime_type=mime_type)
63
118
  return types.Part(inline_data=blob)
64
119
 
@@ -71,7 +126,22 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
71
126
  filename: str,
72
127
  artifact: types.Part,
73
128
  ) -> int:
74
- """Implementation of artifact saving."""
129
+ """Implementation of artifact saving.
130
+
131
+ Args:
132
+ app_name: The name of the application.
133
+ user_id: The ID of the user.
134
+ session_id: The ID of the session.
135
+ filename: The name of the file to save.
136
+ artifact: The artifact to save.
137
+
138
+ Returns:
139
+ The version number of the saved artifact.
140
+
141
+ Raises:
142
+ RuntimeError: If saving the artifact fails.
143
+ ValueError: If the artifact type is not supported.
144
+ """
75
145
  try:
76
146
  # Extract blob data
77
147
  data, mime_type = self._serialize_blob(artifact)
@@ -124,7 +194,22 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
124
194
  filename: str,
125
195
  version: Optional[int] = None,
126
196
  ) -> Optional[types.Part]:
127
- """Implementation of artifact loading."""
197
+ """Implementation of artifact loading.
198
+
199
+ Args:
200
+ app_name: The name of the application.
201
+ user_id: The ID of the user.
202
+ session_id: The ID of the session.
203
+ filename: The name of the file to load.
204
+ version: Optional version number to load. If not provided,
205
+ the latest version will be loaded.
206
+
207
+ Returns:
208
+ The loaded artifact if found, None otherwise.
209
+
210
+ Raises:
211
+ RuntimeError: If loading the artifact fails.
212
+ """
128
213
  try:
129
214
  # Load metadata
130
215
  metadata_file = self._get_artifact_file_path(app_name, user_id, session_id, filename)
@@ -173,7 +258,19 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
173
258
  user_id: str,
174
259
  session_id: str,
175
260
  ) -> List[str]:
176
- """Implementation of artifact key listing."""
261
+ """Implementation of artifact key listing.
262
+
263
+ Args:
264
+ app_name: The name of the application.
265
+ user_id: The ID of the user.
266
+ session_id: The ID of the session.
267
+
268
+ Returns:
269
+ A list of artifact keys (filenames).
270
+
271
+ Raises:
272
+ RuntimeError: If listing artifact keys fails.
273
+ """
177
274
  try:
178
275
  directory = self._get_artifact_directory(app_name, user_id, session_id)
179
276
 
@@ -197,7 +294,17 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
197
294
  session_id: str,
198
295
  filename: str,
199
296
  ) -> None:
200
- """Implementation of artifact deletion."""
297
+ """Implementation of artifact deletion.
298
+
299
+ Args:
300
+ app_name: The name of the application.
301
+ user_id: The ID of the user.
302
+ session_id: The ID of the session.
303
+ filename: The name of the file to delete.
304
+
305
+ Raises:
306
+ RuntimeError: If deleting the artifact fails.
307
+ """
201
308
  try:
202
309
  # Load metadata to find all version files
203
310
  metadata_file = self._get_artifact_file_path(app_name, user_id, session_id, filename)
@@ -226,7 +333,20 @@ class LocalFolderArtifactService(BaseCustomArtifactService):
226
333
  session_id: str,
227
334
  filename: str,
228
335
  ) -> List[int]:
229
- """Implementation of version listing."""
336
+ """Implementation of version listing.
337
+
338
+ Args:
339
+ app_name: The name of the application.
340
+ user_id: The ID of the user.
341
+ session_id: The ID of the session.
342
+ filename: The name of the file to list versions for.
343
+
344
+ Returns:
345
+ A list of version numbers.
346
+
347
+ Raises:
348
+ RuntimeError: If listing versions fails.
349
+ """
230
350
  try:
231
351
  metadata_file = self._get_artifact_file_path(app_name, user_id, session_id, filename)
232
352