Skip to content

Commit

Permalink
Update cloud configure, local StructureRunner, templates. Add poetry …
Browse files Browse the repository at this point in the history
…support. Update README.
  • Loading branch information
zachgiordano committed Nov 22, 2023
1 parent 948665b commit d69d068
Show file tree
Hide file tree
Showing 15 changed files with 553 additions and 1,897 deletions.
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

CLI for the Griptape Framework and Cloud.

## Can I Just Install the CLI?

Sure!

1. Install [pipx](https://github.com/pypa/pipx)
1. Run:
```shell
pipx install git+https://github.com/griptape-ai/griptape-cli.git
```

## Development

```shell
Expand All @@ -23,16 +33,20 @@ Set environment variables:
export GRIPTAPE_CLOUD_API_KEY=<api_key>
```

Note: You can create an API Key using the [frontend](https://cloud-staging.griptape.ai/).
Note: You can create an API Key using the [frontend](https://cloud.griptape.ai/).

To override the Griptape Cloud endpoint used, set the following environment variable:

```shell
export GRIPTAPE_CLOUD_ENDPOINT_URL="https://<endpoint>"
```

Configure the Cloud:

```shell
poetry run gt cloud configure
```

Note: Copy and paste the full 'name: ID' string in the terminal to select

Use the cloud command to make API calls:

```shell
Expand Down
8 changes: 3 additions & 5 deletions griptape/cli/commands/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
from click import echo
from griptape.artifacts import TextArtifact
from griptape.cli.core.app import App
from griptape.cli.core.app_deployer import AppDeployer
from griptape.cli.core.cloud_client import CloudClient
from griptape.cli.core.structure_runner import StructureRunner

from griptape.cli.core.utils.constants import DEFAULT_ENDPOINT_URL


@click.group()
@click.pass_context
Expand Down Expand Up @@ -63,5 +59,7 @@ def run(arg: list[str], directory: str) -> TextArtifact:
Run a Griptape app.
"""

structure_runner = StructureRunner(arg=arg, app_directory=directory)
echo(f"Running app")

structure_runner = StructureRunner(args=arg, app_directory=directory)
structure_runner.run()
83 changes: 56 additions & 27 deletions griptape/cli/commands/cloud.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import json
import os
from typing import Optional
import click
from click import echo
from griptape.cli.core.app_deployer import AppDeployer
from griptape.cli.core.app_packager import AppPackager
from griptape.cli.core.cloud_client import CloudClient
from griptape.cli.core.utils.constants import DEFAULT_ENDPOINT_URL
from InquirerPy import inquirer


@click.group()
Expand All @@ -25,33 +25,37 @@ def cloud(ctx):
)
def configure(endpoint_url: str) -> None:
try:
counter = 0
cloud_client = CloudClient(endpoint_url=endpoint_url)
organizations = cloud_client.list_organizations().json()["organizations"]
organization_choices = click.Choice(
[f"{org['name']}: {org['organization_id']}" for org in organizations]
)
value = click.prompt(
"Select the organization you want to use\n",
type=organization_choices,
show_choices=True,
)
index = organization_choices.choices.index(value)
org = organizations[index]

org_choices = [
f"{counter+1}). {org['name']}: {org['organization_id']}"
for org in organizations
]
org_choice = inquirer.select(
message="Select the organization you want to use:",
choices=org_choices,
).execute()

org = organizations[org_choices.index(org_choice)]

environments = cloud_client.list_environments(
organization_id=org["organization_id"]
).json()["environments"]

environment_choices = click.Choice(
[f"{env['name']}: {env['environment_id']}" for env in environments]
)
value = click.prompt(
"Select the environment you want to use\n",
type=environment_choices,
show_choices=True,
)
index = environment_choices.choices.index(value)
env = environments[index]
counter = 0
environment_choices = [
f"{counter+1}). {env['name']}: {env['environment_id']}"
for env in environments
]

env_choice = inquirer.select(
message="Select the environment you want to use:",
choices=environment_choices,
).execute()

env = environments[environment_choices.index(env_choice)]

profile_name = click.prompt(
"Enter a name for this profile",
Expand Down Expand Up @@ -107,16 +111,42 @@ def list_organizations(endpoint_url: str):
help="Override default endpoint url",
default=DEFAULT_ENDPOINT_URL,
)
def list_organizations(organization_id: str, endpoint_url: str):
def list_environments(organization_id: str, endpoint_url: str):
"""
List Griptape Cloud Organizations.
List Griptape Cloud Environments.
"""

cloud_client = CloudClient(endpoint_url=endpoint_url)
response = cloud_client.list_environments(organization_id=organization_id)
echo(response.json())


@cloud.command(name="list-apps")
@click.option(
"--environment-id",
"-n",
type=str,
required=True,
help="Environment ID to list apps for",
)
@click.option(
"--endpoint-url",
"-e",
type=str,
required=False,
help="Override default endpoint url",
default=DEFAULT_ENDPOINT_URL,
)
def list_apps(environment_id: str, endpoint_url: str):
"""
List Griptape Cloud Apps.
"""

cloud_client = CloudClient(endpoint_url=endpoint_url)
response = cloud_client.list_apps(environment_id=environment_id)
echo(response.json())


@cloud.command(name="create-app")
@click.option(
"--name",
Expand Down Expand Up @@ -194,11 +224,10 @@ def create_deployment(app_id: str, directory: str, endpoint_url: str) -> None:

cloud_client = CloudClient(endpoint_url=endpoint_url)

app_deployer = AppDeployer(
app_packager = AppPackager(
app_directory=directory,
endpoint_url=endpoint_url,
)
source = app_deployer.get_deployment_source()
source = app_packager.get_deployment_source()

deployment_data = {"source": {"zip_file": {"base64_content": source}}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@


@define
class AppDeployer:
class AppPackager:
app_directory: str = field(kw_only=True)
endpoint_url: str = field(kw_only=True)

def __attrs_post_init__(self):
self.app_directory = os.path.abspath(self.app_directory)
Expand Down
4 changes: 4 additions & 0 deletions griptape/cli/core/cloud_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ def list_environments(self, organization_id: str) -> Response:
)
return requests.get(url=url, headers=self._get_authorization_headers())

def list_apps(self, environment_id: str) -> Response:
url = urljoin(self.endpoint_url, f"environments/{environment_id}/apps")
return requests.get(url=url, headers=self._get_authorization_headers())

def create_app(self, app_data: dict, environment_id: Optional[str]):
if not environment_id:
profile_data: dict = self._extract_profile_data_from_local_storage()
Expand Down
25 changes: 14 additions & 11 deletions griptape/cli/core/structure_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
from typing import Optional

from attr import Factory, define, field
from dotenv import load_dotenv


@define
class StructureRunner:
arg: list[str] = field(kw_only=True)
args: list[str] = field(kw_only=True)
app_directory: Optional[str] = field(
kw_only=True, default=Factory(lambda: os.getcwd())
)
Expand All @@ -20,25 +19,29 @@ def __attrs_post_init__(self):
def run(self):
try:
sys.path.append(self.app_directory)
self._install_pip_dependencies()
self._load_dotenv()
if not self._install_pip_dependencies():
self._install_poetry_dependencies()
from app import init_structure

try:
return init_structure().run(*self.arg)
return init_structure(*self.args).run(*self.args)
except Exception as e:
raise Exception(f"Error running app: {e}")
except Exception as e:
raise Exception(f"App doesn't exist: {e}")
raise Exception(f"Error importing app: {e}")

def _install_pip_dependencies(self) -> None:
def _install_pip_dependencies(self) -> bool:
requirements_path = os.path.join(self.app_directory, "requirements.txt")
if os.path.exists(requirements_path):
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "-r", requirements_path]
)
return True
return False

def _load_dotenv(self) -> None:
dotenv_path = os.path.join(self.app_directory, ".env")
if os.path.exists(dotenv_path):
load_dotenv(dotenv_path)
def _install_poetry_dependencies(self) -> None:
pyproject_path = os.path.join(self.app_directory, "pyproject.toml")
if os.path.exists(pyproject_path):
subprocess.check_call(
["poetry", "install", "--directory", self.app_directory]
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
load_dotenv()


def init_structure() -> Structure:
def init_structure(*args) -> Structure:
return Agent()
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ authors = []
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"
griptape = "*"
python = ">=3.9,<3.12"
griptape = { git = "https://github.com/griptape-ai/griptape", branch = "dev" }
python-dotenv = "*"

[build-system]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
griptape
griptape@git+https://github.com/griptape-ai/griptape@dev
python-dotenv
7 changes: 6 additions & 1 deletion griptape/cli/core/utils/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
DEFAULT_ENDPOINT_URL = "https://api.cloud.griptape.ai"
import os


DEFAULT_ENDPOINT_URL = os.environ.get(
"GRIPTAPE_CLOUD_ENDPOINT_URL", "https://api.cloud.griptape.ai"
)
Loading

0 comments on commit d69d068

Please sign in to comment.