Skip to content

Commit 1625976

Browse files
wanlin31copybara-github
authored andcommitted
feat: introduce gaos sdk libs
PiperOrigin-RevId: 919824238
1 parent ca97c58 commit 1625976

202 files changed

Lines changed: 26326 additions & 3 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

google/genai/_gaos/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
# pyformat: disable
16+
17+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
18+
19+
from ._version import (
20+
__title__,
21+
__version__,
22+
__openapi_doc_version__,
23+
__gen_version__,
24+
__user_agent__,
25+
)
26+
from .sdk import *
27+
from .sdkconfiguration import *
28+
from . import resources
29+
30+
31+
VERSION: str = __version__
32+
OPENAPI_DOC_VERSION = __openapi_doc_version__
33+
SPEAKEASY_GENERATOR_VERSION = __gen_version__
34+
USER_AGENT = __user_agent__
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
# pyformat: disable
16+
17+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
18+
19+
from .sdkhooks import *
20+
from .types import *
21+
from .registration import *
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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+
# pyformat: disable
16+
17+
"""Google GenAI authentication hooks for the embedded Speakeasy SDK."""
18+
19+
from __future__ import annotations
20+
21+
from typing import Any, Callable, Mapping, Optional, Union, cast
22+
23+
import httpx
24+
25+
from .. import types, utils
26+
from .types import BeforeRequestContext, BeforeRequestHook
27+
28+
29+
GOOGLE_GENAI_API_REVISION = "2026-05-20"
30+
_MANAGED_BEARER_AUTH = "google_genai_managed_bearer_auth"
31+
32+
33+
class GoogleGenAISecurityProvider:
34+
"""Callable security source that keeps generated auth refreshes retry-safe."""
35+
36+
def __init__(
37+
self,
38+
*,
39+
access_token: Callable[[], str],
40+
default_headers: Optional[Mapping[str, str]] = None,
41+
) -> None:
42+
self._access_token = access_token
43+
self._default_headers = dict(default_headers or {})
44+
self._pending_access_token: Optional[str] = None
45+
46+
def __call__(self) -> types.Security:
47+
if self._pending_access_token is None:
48+
self._pending_access_token = self._access_token()
49+
50+
return types.Security(
51+
access_token=self._pending_access_token,
52+
default_headers=self._default_headers or None,
53+
)
54+
55+
def consume(self) -> None:
56+
self._pending_access_token = None
57+
58+
59+
class GoogleGenAIAuthHook(BeforeRequestHook):
60+
"""Applies Google GenAI headers and custom auth before sending requests."""
61+
62+
def before_request(
63+
self,
64+
hook_ctx: BeforeRequestContext,
65+
request: httpx.Request,
66+
) -> Union[httpx.Request, Exception]:
67+
security = _resolve_security(hook_ctx.security_source)
68+
69+
_apply_default_headers(security, request)
70+
_apply_api_revision(hook_ctx, request)
71+
_apply_user_project(hook_ctx, request)
72+
_apply_auth(security, request)
73+
74+
return request
75+
76+
77+
def _resolve_security(security_source: Any) -> Optional[types.Security]:
78+
security = security_source
79+
80+
if callable(security_source):
81+
security = security_source()
82+
consume = getattr(security_source, "consume", None)
83+
if callable(consume):
84+
consume()
85+
86+
security = utils.get_security_from_env(security, types.Security)
87+
if security is None:
88+
return None
89+
90+
if isinstance(security, types.Security):
91+
return security
92+
93+
if isinstance(security, Mapping):
94+
return types.Security(**security)
95+
96+
return cast(types.Security, security)
97+
98+
99+
def _apply_default_headers(
100+
security: Optional[types.Security], request: httpx.Request
101+
) -> None:
102+
headers = security.default_headers if security else None
103+
for key, value in (headers or {}).items():
104+
if request.headers.get(key) is None:
105+
request.headers[key] = value
106+
107+
108+
def _apply_api_revision(
109+
hook_ctx: BeforeRequestContext, request: httpx.Request
110+
) -> None:
111+
if request.headers.get("Api-Revision") is not None:
112+
return
113+
114+
api_revision = hook_ctx.config.globals.api_revision
115+
request.headers["Api-Revision"] = api_revision or GOOGLE_GENAI_API_REVISION
116+
117+
118+
def _apply_user_project(
119+
hook_ctx: BeforeRequestContext, request: httpx.Request
120+
) -> None:
121+
user_project = hook_ctx.config.globals.user_project
122+
if user_project and request.headers.get("x-goog-user-project") is None:
123+
request.headers["x-goog-user-project"] = user_project
124+
125+
126+
def _has_auth_headers(request: httpx.Request) -> bool:
127+
return (
128+
request.headers.get("authorization") is not None
129+
or request.headers.get("x-goog-api-key") is not None
130+
)
131+
132+
133+
def _has_user_auth_headers(request: httpx.Request) -> bool:
134+
return (
135+
not request.extensions.get(_MANAGED_BEARER_AUTH)
136+
and _has_auth_headers(request)
137+
)
138+
139+
140+
def _apply_auth(
141+
security: Optional[types.Security], request: httpx.Request
142+
) -> None:
143+
if security is None or _has_user_auth_headers(request):
144+
return
145+
146+
if security.api_key:
147+
request.extensions.pop(_MANAGED_BEARER_AUTH, None)
148+
request.headers["x-goog-api-key"] = security.api_key
149+
return
150+
151+
if security.access_token:
152+
request.extensions[_MANAGED_BEARER_AUTH] = True
153+
request.headers["Authorization"] = _bearer(security.access_token)
154+
155+
156+
def _bearer(token: str) -> str:
157+
return token if token.lower().startswith("bearer ") else f"Bearer {token}"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
# pyformat: disable
16+
17+
from .types import Hooks
18+
19+
20+
# This file is only ever generated once on the first generation and then is free to be modified.
21+
# Any hooks you wish to add should be registered in the init_hooks function. Feel free to define them
22+
# in this file or in separate files in the hooks folder.
23+
24+
25+
def init_hooks(hooks: Hooks):
26+
# pylint: disable=unused-argument
27+
"""Add hooks by calling hooks.register{sdk_init/before_request/after_success/after_error}Hook
28+
with an instance of a hook that implements that specific Hook interface
29+
Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance"""
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
# pyformat: disable
16+
17+
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
18+
19+
import httpx
20+
from .types import (
21+
SDKInitHook,
22+
BeforeRequestContext,
23+
BeforeRequestHook,
24+
AfterSuccessContext,
25+
AfterSuccessHook,
26+
AfterErrorContext,
27+
AfterErrorHook,
28+
Hooks,
29+
)
30+
from .registration import init_hooks
31+
from .google_genai_auth import GoogleGenAIAuthHook
32+
from typing import List, Optional, Tuple
33+
from ..sdkconfiguration import SDKConfiguration
34+
35+
36+
class SDKHooks(Hooks):
37+
def __init__(self) -> None:
38+
self.sdk_init_hooks: List[SDKInitHook] = []
39+
self.before_request_hooks: List[BeforeRequestHook] = []
40+
self.after_success_hooks: List[AfterSuccessHook] = []
41+
self.after_error_hooks: List[AfterErrorHook] = []
42+
init_hooks(self)
43+
self.register_before_request_hook(GoogleGenAIAuthHook())
44+
45+
def register_sdk_init_hook(self, hook: SDKInitHook) -> None:
46+
self.sdk_init_hooks.append(hook)
47+
48+
def register_before_request_hook(self, hook: BeforeRequestHook) -> None:
49+
self.before_request_hooks.append(hook)
50+
51+
def register_after_success_hook(self, hook: AfterSuccessHook) -> None:
52+
self.after_success_hooks.append(hook)
53+
54+
def register_after_error_hook(self, hook: AfterErrorHook) -> None:
55+
self.after_error_hooks.append(hook)
56+
57+
def sdk_init(self, config: SDKConfiguration) -> SDKConfiguration:
58+
for hook in self.sdk_init_hooks:
59+
config = hook.sdk_init(config)
60+
return config
61+
62+
def before_request(
63+
self, hook_ctx: BeforeRequestContext, request: httpx.Request
64+
) -> httpx.Request:
65+
for hook in self.before_request_hooks:
66+
out = hook.before_request(hook_ctx, request)
67+
if isinstance(out, Exception):
68+
raise out
69+
request = out
70+
71+
return request
72+
73+
def after_success(
74+
self, hook_ctx: AfterSuccessContext, response: httpx.Response
75+
) -> httpx.Response:
76+
for hook in self.after_success_hooks:
77+
out = hook.after_success(hook_ctx, response)
78+
if isinstance(out, Exception):
79+
raise out
80+
response = out
81+
return response
82+
83+
def after_error(
84+
self,
85+
hook_ctx: AfterErrorContext,
86+
response: Optional[httpx.Response],
87+
error: Optional[Exception],
88+
) -> Tuple[Optional[httpx.Response], Optional[Exception]]:
89+
for hook in self.after_error_hooks:
90+
result = hook.after_error(hook_ctx, response, error)
91+
if isinstance(result, Exception):
92+
raise result
93+
response, error = result
94+
return response, error

0 commit comments

Comments
 (0)