generated from griptape-ai/griptape-extension-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9a51a3c
commit aacf0ed
Showing
31 changed files
with
1,397 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,143 +1,47 @@ | ||
# Griptape Extension Template | ||
# Griptape Google Extension | ||
|
||
A Github template repository for creating Griptape extensions. | ||
## Overview | ||
This extension provides several [Tools](https://docs.griptape.ai/stable/griptape-tools/) for various Google services. | ||
|
||
## Getting Started | ||
```python | ||
import os | ||
|
||
Via github web page: | ||
from griptape.structures import Agent | ||
from griptape.google.tools import GoogleGmailTool | ||
|
||
Click on `Use this template` | ||
gmail_tool = GoogleGmailTool( | ||
service_account_credentials={ | ||
"type": os.environ["GOOGLE_ACCOUNT_TYPE"], | ||
"project_id": os.environ["GOOGLE_PROJECT_ID"], | ||
"private_key_id": os.environ["GOOGLE_PRIVATE_KEY_ID"], | ||
"private_key": os.environ["GOOGLE_PRIVATE_KEY"], | ||
"client_email": os.environ["GOOGLE_CLIENT_EMAIL"], | ||
"client_id": os.environ["GOOGLE_CLIENT_ID"], | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": os.environ["GOOGLE_CERT_URL"], | ||
}, | ||
owner_email=os.environ["GOOGLE_OWNER_EMAIL"], | ||
) | ||
|
||
![](https://docs.github.com/assets/cb-36544/images/help/repository/use-this-template-button.png) | ||
agent = Agent(tools=[gmail_tool]) | ||
|
||
|
||
Via `gh`: | ||
|
||
``` | ||
$ gh repo create griptape-extension-name -p griptape/griptape-extension-template | ||
``` | ||
|
||
## What is a Griptape Extension? | ||
|
||
Griptape Extensions can add new functionality to the [Griptape framework](https://github.com/griptape-ai/griptape), such as new Tools, Drivers, Tasks, or Structures. | ||
With extensions, you can integrate custom APIs, tools, and services into the Griptape ecosystem. | ||
|
||
This repository provides a recommended structure for organizing your extension code, as well as helpful tools for testing and development. | ||
|
||
## Extension Structure | ||
|
||
The template repository is structured as follows: | ||
|
||
```bash | ||
tree -I __init__.py -I __pycache__ | ||
|
||
├── griptape | ||
│ └── extension_name # Name whatever you want | ||
│ └── tools | ||
│ └── reverse_string | ||
│ └── tool.py | ||
...more directories for other interfaces (drivers, tasks, structures, etc)... | ||
└── tests | ||
└── unit | ||
└── tools | ||
└── test_reverse_string_tool.py | ||
├── examples | ||
└── tools | ||
└── example_agent.py # Example usage of the extension | ||
├── LICENSE # Choose the appropriate license | ||
├── Makefile # Contains useful commands for development | ||
├── pyproject.toml # Contains the project's metadata | ||
├── README.md # Describes the extension and how to use it | ||
agent.run( | ||
"Create a draft email in Gmail to [email protected] with the subject 'Test Draft', the body " | ||
"'This is a test draft email.'", | ||
) | ||
``` | ||
|
||
## Development | ||
|
||
### Poetry | ||
|
||
This project uses [Poetry](https://python-poetry.org/) for dependency management. | ||
It is recommended to configure Poetry to use [in-project](https://python-poetry.org/docs/configuration/#virtualenvsin-project) virtual environments: | ||
|
||
```bash | ||
poetry config virtualenvs.in-project true | ||
``` | ||
|
||
This will create a `.venv` directory in the project root, where the virtual environment will be stored. | ||
This ensures that the virtual environment is always in the same location, regardless of where the project is cloned. | ||
|
||
### Useful Commands | ||
|
||
#### Installing Dependencies | ||
## Installation | ||
|
||
Poetry: | ||
```bash | ||
make install | ||
poetry add https://github.com/griptape-ai/griptape-google.git | ||
``` | ||
|
||
#### Running Tests | ||
|
||
Pip: | ||
```bash | ||
make test | ||
pip install git+https://github.com/griptape-ai/griptape-google.git | ||
``` | ||
|
||
#### Running Checks (linting, formatting, etc) | ||
|
||
```bash | ||
make check | ||
``` | ||
|
||
#### Running Formatter | ||
|
||
```bash | ||
make format | ||
``` | ||
|
||
#### Running Example | ||
|
||
This template includes an [example](https://github.com/griptape-ai/tool-template/blob/main/examples/tools/example_agent.py) demonstrating how to use the extension. It shows how to import the `ReverseStringTool`, provide it to an Agent, and run it. | ||
|
||
1. Set the required environment variables. The example needs the `OPENAI_API_KEY` environment variable to be set. | ||
2. Run the example: | ||
|
||
```bash | ||
poetry run python examples/tools/example_agent.py | ||
``` | ||
|
||
If successful, you should see: | ||
``` | ||
[11/18/24 14:55:14] INFO ToolkitTask 6bb7fa5581d147b2a39e801631c98005 | ||
Input: Use the ReverseStringTool to reverse 'Griptape' | ||
[11/18/24 14:55:15] INFO Subtask c3036471831144529b8d5300c6849203 | ||
Actions: [ | ||
{ | ||
"tag": "call_VE4tGBFL7iB7VDbkKaIFIkwY", | ||
"name": "ReverseStringTool", | ||
"path": "reverse_string", | ||
"input": { | ||
"values": { | ||
"input": "Griptape" | ||
} | ||
} | ||
} | ||
] | ||
INFO Subtask c3036471831144529b8d5300c6849203 | ||
Response: epatpirG | ||
[11/18/24 14:55:16] INFO ToolkitTask 6bb7fa5581d147b2a39e801631c98005 | ||
Output: The reversed string of "Griptape" is "epatpirG". | ||
``` | ||
|
||
## Installing in Other Projects | ||
|
||
Extensions are designed to be shared. Extensions are made to easily install into existing Python projects. | ||
|
||
The easiest way to include your extension into an existing project is to install directly from the repository, like so: | ||
```bash | ||
poetry add git+https://github.com/{your-org}/{your-extension-name}.git | ||
``` | ||
|
||
To install a local copy of the extension for development, run: | ||
```bash | ||
poetry add -e /path/to/your/extension | ||
``` | ||
|
||
Any changes made to the extension will be automatically reflected in the project without needing to reinstall it. | ||
|
||
Advanced customers may seek to publish their extensions to PyPi. Those instructions are beyond the scope of this README. |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import os | ||
|
||
from griptape.structures import Agent | ||
from griptape.google.tools import GoogleCalendarTool | ||
|
||
# Create the GoogleCalendarTool tool | ||
google_calendarendar_tool = GoogleCalendarTool( | ||
service_account_credentials={ | ||
"type": os.environ["GOOGLE_ACCOUNT_TYPE"], | ||
"project_id": os.environ["GOOGLE_PROJECT_ID"], | ||
"private_key_id": os.environ["GOOGLE_PRIVATE_KEY_ID"], | ||
"private_key": os.environ["GOOGLE_PRIVATE_KEY"], | ||
"client_email": os.environ["GOOGLE_CLIENT_EMAIL"], | ||
"client_id": os.environ["GOOGLE_CLIENT_ID"], | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": os.environ["GOOGLE_CERT_URL"], | ||
}, | ||
owner_email=os.environ["GOOGLE_OWNER_EMAIL"], | ||
) | ||
|
||
# Set up an agent using the GoogleCalendarTool tool | ||
agent = Agent(tools=[google_calendarendar_tool]) | ||
|
||
# Task: Get upcoming events from a Google calendar | ||
agent.run( | ||
"Get me the details of the next upcoming event from my primary calendar.", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import os | ||
|
||
from griptape.structures import Agent | ||
from griptape.google.tools import GoogleDocsTool | ||
|
||
# Create the GoogleDocsTool tool | ||
google_docs_tool = GoogleDocsTool( | ||
service_account_credentials={ | ||
"type": os.environ["GOOGLE_ACCOUNT_TYPE"], | ||
"project_id": os.environ["GOOGLE_PROJECT_ID"], | ||
"private_key_id": os.environ["GOOGLE_PRIVATE_KEY_ID"], | ||
"private_key": os.environ["GOOGLE_PRIVATE_KEY"], | ||
"client_email": os.environ["GOOGLE_CLIENT_EMAIL"], | ||
"client_id": os.environ["GOOGLE_CLIENT_ID"], | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": os.environ["GOOGLE_CERT_URL"], | ||
}, | ||
owner_email=os.environ["GOOGLE_OWNER_EMAIL"], | ||
) | ||
|
||
# Set up an agent using the GoogleDocsTool tool | ||
agent = Agent(tools=[google_docs_tool]) | ||
|
||
# Task: Create a new Google Doc and save content to it | ||
agent.run( | ||
"Create doc with name 'test_creation' in test folder with content 'Hey, Tony.", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import os | ||
|
||
from griptape.structures import Agent | ||
from griptape.google.tools import GoogleDriveTool | ||
|
||
# Create the GoogleDriveTool tool | ||
google_drive_tool = GoogleDriveTool( | ||
service_account_credentials={ | ||
"type": os.environ["GOOGLE_ACCOUNT_TYPE"], | ||
"project_id": os.environ["GOOGLE_PROJECT_ID"], | ||
"private_key_id": os.environ["GOOGLE_PRIVATE_KEY_ID"], | ||
"private_key": os.environ["GOOGLE_PRIVATE_KEY"], | ||
"client_email": os.environ["GOOGLE_CLIENT_EMAIL"], | ||
"client_id": os.environ["GOOGLE_CLIENT_ID"], | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": os.environ["GOOGLE_CERT_URL"], | ||
}, | ||
owner_email=os.environ["GOOGLE_OWNER_EMAIL"], | ||
) | ||
|
||
# Set up an agent using the GoogleDriveTool tool | ||
agent = Agent(tools=[google_drive_tool]) | ||
|
||
# Task: Save content to my Google Drive (default directory is root) | ||
agent.run( | ||
"Save the content 'Hi this is Tony' in a filed named 'hello.txt' to my Drive.", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import os | ||
|
||
from griptape.structures import Agent | ||
from griptape.google.tools import GoogleGmailTool | ||
|
||
# Create the GoogleGmailTool tool | ||
gmail_tool = GoogleGmailTool( | ||
service_account_credentials={ | ||
"type": os.environ["GOOGLE_ACCOUNT_TYPE"], | ||
"project_id": os.environ["GOOGLE_PROJECT_ID"], | ||
"private_key_id": os.environ["GOOGLE_PRIVATE_KEY_ID"], | ||
"private_key": os.environ["GOOGLE_PRIVATE_KEY"], | ||
"client_email": os.environ["GOOGLE_CLIENT_EMAIL"], | ||
"client_id": os.environ["GOOGLE_CLIENT_ID"], | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": os.environ["GOOGLE_CERT_URL"], | ||
}, | ||
owner_email=os.environ["GOOGLE_OWNER_EMAIL"], | ||
) | ||
|
||
# Set up an agent using the GoogleGmailTool tool | ||
agent = Agent(tools=[gmail_tool]) | ||
|
||
# Task: Create a draft email in Gmail | ||
agent.run( | ||
"Create a draft email in Gmail to [email protected] with the subject 'Test Draft', the body " | ||
"'This is a test draft email.'", | ||
) |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from .base_google_tool import BaseGoogleTool | ||
from .google_calendar.tool import GoogleCalendarTool | ||
from .google_docs.tool import GoogleDocsTool | ||
from .google_drive.tool import GoogleDriveTool | ||
from .google_gmail.tool import GoogleGmailTool | ||
|
||
__all__ = [ | ||
"BaseGoogleTool", | ||
"GoogleCalendarTool", | ||
"GoogleDocsTool", | ||
"GoogleDriveTool", | ||
"GoogleGmailTool", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from __future__ import annotations | ||
|
||
from abc import ABC | ||
from typing import Any | ||
|
||
from attrs import define, field | ||
|
||
from griptape.tools import BaseTool | ||
|
||
|
||
@define | ||
class BaseGoogleTool(BaseTool, ABC): | ||
DRIVE_FILE_SCOPES = ["https://www.googleapis.com/auth/drive.file"] | ||
|
||
DRIVE_AUTH_SCOPES = ["https://www.googleapis.com/auth/drive"] | ||
|
||
owner_email: str = field(kw_only=True) | ||
service_account_credentials: dict = field(kw_only=True) | ||
|
||
def _build_client(self, scopes: list[str], service_name: str, version: str) -> Any: | ||
from google.oauth2 import service_account | ||
from googleapiclient.discovery import build | ||
|
||
credentials = service_account.Credentials.from_service_account_info( | ||
self.service_account_credentials, | ||
scopes=scopes, | ||
) | ||
|
||
return build( | ||
serviceName=service_name, | ||
version=version, | ||
credentials=credentials.with_subject(self.owner_email), | ||
) | ||
|
||
def _convert_path_to_file_id(self, service: Any, path: str) -> str | None: | ||
parts = path.split("/") | ||
current_id = "root" | ||
|
||
for idx, part in enumerate(parts): | ||
if idx == len(parts) - 1: | ||
query = f"name='{part}' and '{current_id}' in parents" | ||
else: | ||
query = f"name='{part}' and '{current_id}' in parents and mimeType='application/vnd.google-apps.folder'" | ||
|
||
response = service.files().list(q=query).execute() | ||
files = response.get("files", []) | ||
|
||
if not files: | ||
if idx != len(parts) - 1: | ||
folder_metadata = { | ||
"name": part, | ||
"mimeType": "application/vnd.google-apps.folder", | ||
"parents": [current_id], | ||
} | ||
folder = ( | ||
service.files() | ||
.create(body=folder_metadata, fields="id") | ||
.execute() | ||
) | ||
current_id = folder.get("id") | ||
else: | ||
current_id = None | ||
else: | ||
current_id = files[0]["id"] | ||
|
||
return current_id |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
google-api-python-client |
Oops, something went wrong.