Skip to content

Commit 995dc03

Browse files
committed
feat: code links updates
1 parent 02458f1 commit 995dc03

File tree

9 files changed

+80
-10
lines changed

9 files changed

+80
-10
lines changed

autogpt_platform/backend/backend/blocks/github/issues.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
)
1414

1515

16+
# --8<-- [start:GithubCommentBlock]
1617
class GithubCommentBlock(Block):
1718
class Input(BlockSchema):
1819
credentials: GithubCredentialsInput = GithubCredentialsField("repo")
@@ -104,6 +105,9 @@ def run(
104105
yield "error", f"Failed to post comment: {str(e)}"
105106

106107

108+
# --8<-- [end:GithubCommentBlock]
109+
110+
107111
class GithubMakeIssueBlock(Block):
108112
class Input(BlockSchema):
109113
credentials: GithubCredentialsInput = GithubCredentialsField("repo")

autogpt_platform/backend/backend/blocks/google/_auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
from backend.data.model import CredentialsField, CredentialsMetaInput
77
from backend.util.settings import Secrets
88

9+
# --8<-- [start:GoogleOAuthIsConfigured]
910
secrets = Secrets()
1011
GOOGLE_OAUTH_IS_CONFIGURED = bool(
1112
secrets.google_client_id and secrets.google_client_secret
1213
)
13-
14+
# --8<-- [end: GoogleOAuthIsConfigured]
1415
GoogleCredentials = OAuth2Credentials
1516
GoogleCredentialsInput = CredentialsMetaInput[Literal["google"], Literal["oauth2"]]
1617

autogpt_platform/backend/backend/integrations/oauth/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .google import GoogleOAuthHandler
44
from .notion import NotionOAuthHandler
55

6+
# --8<-- [start:HANDLERS_BY_NAMEExample]
67
HANDLERS_BY_NAME: dict[str, type[BaseOAuthHandler]] = {
78
handler.PROVIDER_NAME: handler
89
for handler in [
@@ -11,5 +12,6 @@
1112
NotionOAuthHandler,
1213
]
1314
}
15+
# --8<-- [end: HANDLERS_BY_NAMEExample]
1416

1517
__all__ = ["HANDLERS_BY_NAME"]

autogpt_platform/backend/backend/integrations/oauth/base.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,36 @@
66

77

88
class BaseOAuthHandler(ABC):
9+
# --8<-- [start: BaseOAuthHandler1]
910
PROVIDER_NAME: ClassVar[str]
1011
DEFAULT_SCOPES: ClassVar[list[str]] = []
12+
# --8<-- [end: BaseOAuthHandler1]
1113

1214
@abstractmethod
15+
# --8<-- [start: BaseOAuthHandler2]
1316
def __init__(self, client_id: str, client_secret: str, redirect_uri: str): ...
17+
# --8<-- [end: BaseOAuthHandler2]
1418

1519
@abstractmethod
20+
# --8<-- [start: BaseOAuthHandler3]
1621
def get_login_url(self, scopes: list[str], state: str) -> str:
22+
# --8<-- [end: BaseOAuthHandler3]
1723
"""Constructs a login URL that the user can be redirected to"""
1824
...
1925

2026
@abstractmethod
27+
# --8<-- [start: BaseOAuthHandler4]
2128
def exchange_code_for_tokens(
2229
self, code: str, scopes: list[str]
2330
) -> OAuth2Credentials:
31+
# --8<-- [end: BaseOAuthHandler4]
2432
"""Exchanges the acquired authorization code from login for a set of tokens"""
2533
...
2634

2735
@abstractmethod
36+
# --8<-- [start: BaseOAuthHandler5]
2837
def _refresh_tokens(self, credentials: OAuth2Credentials) -> OAuth2Credentials:
38+
# --8<-- [end: BaseOAuthHandler5]
2939
"""Implements the token refresh mechanism"""
3040
...
3141

autogpt_platform/backend/backend/integrations/oauth/github.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .base import BaseOAuthHandler
99

1010

11+
# --8<-- [start:GithubOAuthHandler]
1112
class GitHubOAuthHandler(BaseOAuthHandler):
1213
"""
1314
Based on the documentation at:
@@ -119,3 +120,6 @@ def _request_username(self, access_token: str) -> str | None:
119120

120121
# Get the login (username)
121122
return response.json().get("login")
123+
124+
125+
# --8<-- [end:GithubOAuthHandler]

autogpt_platform/backend/backend/integrations/oauth/google.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
logger = logging.getLogger(__name__)
1515

1616

17+
# --8<-- [start:GoogleOAuthHandler]
1718
class GoogleOAuthHandler(BaseOAuthHandler):
1819
"""
1920
Based on the documentation at https://developers.google.com/identity/protocols/oauth2/web-server
@@ -27,6 +28,8 @@ class GoogleOAuthHandler(BaseOAuthHandler):
2728
"openid",
2829
]
2930

31+
# --8<-- [end: GoogleOAuthHandler]
32+
3033
def __init__(self, client_id: str, client_secret: str, redirect_uri: str):
3134
self.client_id = client_id
3235
self.client_secret = client_secret

autogpt_platform/backend/backend/util/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,12 @@ class Secrets(UpdateTrackingModel["Secrets"], BaseSettings):
177177
)
178178

179179
# OAuth server credentials for integrations
180+
# --8<-- [start: OAuthServerCredentialsExample]
180181
github_client_id: str = Field(default="", description="GitHub OAuth client ID")
181182
github_client_secret: str = Field(
182183
default="", description="GitHub OAuth client secret"
183184
)
185+
# --8<-- [end: OAuthServerCredentialsExample]
184186
google_client_id: str = Field(default="", description="Google OAuth client ID")
185187
google_client_secret: str = Field(
186188
default="", description="Google OAuth client secret"

docs/content/server/new_blocks.md

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ for a service that we already have OAuth2 support for.
115115

116116
Implementing the block itself is relatively simple. On top of the instructions above,
117117
you're going to add a `credentials` parameter to the `Input` model and the `run` method:
118+
118119
```python
119120
from autogpt_libs.supabase_integration_credentials_store.types import (
120121
APIKeyCredentials,
@@ -191,10 +192,12 @@ class BlockWithAPIKeyAndOAuth(Block):
191192
) -> BlockOutput:
192193
...
193194
```
195+
194196
The credentials will be automagically injected by the executor in the back end.
195197

196198
The `APIKeyCredentials` and `OAuth2Credentials` models are defined [here](https://github.com/Significant-Gravitas/AutoGPT/blob/master/rnd/autogpt_libs/autogpt_libs/supabase_integration_credentials_store/types.py).
197199
To use them in e.g. an API request, you can either access the token directly:
200+
198201
```python
199202
# credentials: APIKeyCredentials
200203
response = requests.post(
@@ -212,7 +215,9 @@ response = requests.post(
212215
},
213216
)
214217
```
218+
215219
or use the shortcut `credentials.bearer()`:
220+
216221
```python
217222
# credentials: APIKeyCredentials | OAuth2Credentials
218223
response = requests.post(
@@ -227,25 +232,64 @@ To add support for a new OAuth2-authenticated service, you'll need to add an `OA
227232
All our existing handlers and the base class can be found [here][OAuth2 handlers].
228233

229234
Every handler must implement the following parts of the [`BaseOAuthHandler`] interface:
230-
- `PROVIDER_NAME`
231-
- `__init__(client_id, client_secret, redirect_uri)`
232-
- `get_login_url(scopes, state)`
233-
- `exchange_code_for_tokens(code)`
234-
- `_refresh_tokens(credentials)`
235+
236+
```python
237+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/base.py:BaseOAuthHandler1"
238+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/base.py:BaseOAuthHandler2"
239+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/base.py:BaseOAuthHandler3"
240+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/base.py:BaseOAuthHandler4"
241+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/base.py:BaseOAuthHandler5"
242+
```
235243

236244
As you can see, this is modeled after the standard OAuth2 flow.
237245

238246
Aside from implementing the `OAuthHandler` itself, adding a handler into the system requires two more things:
239-
- Adding the handler class to `HANDLERS_BY_NAME` [here](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/integrations/oauth/__init__.py)
240-
- Adding `{provider}_client_id` and `{provider}_client_secret` to the application's `Secrets` [here](https://github.com/Significant-Gravitas/AutoGPT/blob/e3f35d79c7e9fc6ee0cabefcb73e0fad15a0ce2d/autogpt_platform/backend/backend/util/settings.py#L132)
247+
248+
- Adding the handler class to `HANDLERS_BY_NAME` under [`integrations/oauth/__init__.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/integrations/oauth/__init__.py)
249+
250+
```python title="autogpt_platform/backend/backend/integrations/oauth/__init__.py"
251+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/__init__.py:HANDLERS_BY_NAMEExample"
252+
```
253+
254+
- Adding `{provider}_client_id` and `{provider}_client_secret` to the application's `Secrets` under [`util/settings.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/util/settings.py)
255+
256+
```python title="autogpt_platform/backend/backend/util/settings.py"
257+
--8<-- "autogpt_platform/backend/backend/util/settings.py:OAuthServerCredentialsExample"
258+
```
241259

242260
[OAuth2 handlers]: https://github.com/Significant-Gravitas/AutoGPT/tree/master/autogpt_platform/backend/backend/integrations/oauth
243261
[`BaseOAuthHandler`]: https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/integrations/oauth/base.py
244262

245263
#### Example: GitHub integration
264+
246265
- GitHub blocks with API key + OAuth2 support: [`blocks/github`](https://github.com/Significant-Gravitas/AutoGPT/tree/master/autogpt_platform/backend/backend/blocks/github/)
266+
267+
```python title="blocks/github/issues.py"
268+
--8<-- "autogpt_platform/backend/backend/blocks/github/issues.py:GithubCommentBlock"
269+
```
270+
247271
- GitHub OAuth2 handler: [`integrations/oauth/github.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/integrations/oauth/github.py)
248272

273+
```python title="blocks/github/github.py"
274+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/github.py:GithubOAuthHandler"
275+
```
276+
277+
#### Example: Google integration
278+
279+
- Google OAuth2 handler: [`integrations/oauth/google.py`](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/backend/backend/integrations/oauth/google.py)
280+
281+
```python title="integrations/oauth/google.py"
282+
--8<-- "autogpt_platform/backend/backend/integrations/oauth/google.py:GoogleOAuthHandler"
283+
```
284+
285+
You can see that google has defined a `DEFAULT_SCOPES` variable, this is used to set the scopes that are requested no matter what the user asks for.
286+
287+
```python title="blocks/google/_auth.py"
288+
--8<-- "autogpt_platform/backend/backend/blocks/google/_auth.py:GoogleOAuthIsConfigured"
289+
```
290+
291+
You can also see that `GOOGLE_OAUTH_IS_CONFIGURED` is used to disable the blocks that require OAuth if the oauth is not configured. This is in the `__init__` method of each block. This is because there is no api key fallback for google blocks so we need to make sure that the oauth is configured before we allow the user to use the blocks.
292+
249293
## Key Points to Remember
250294

251295
- **Unique ID**: Give your block a unique ID in the **init** method.

docs/mkdocs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ markdown_extensions:
136136
- pymdownx.mark
137137
- pymdownx.smartsymbols
138138
- pymdownx.snippets:
139-
auto_append:
140-
- includes/abbreviations.md
139+
base_path: ['.','../']
140+
check_paths: true
141141
- pymdownx.superfences:
142142
custom_fences:
143143
- name: mermaid

0 commit comments

Comments
 (0)