agenta 0.1.18__tar.gz → 0.1.19__tar.gz

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.

Potentially problematic release.


This version of agenta might be problematic. Click here for more details.

Files changed (29) hide show
  1. {agenta-0.1.18 → agenta-0.1.19}/PKG-INFO +1 -1
  2. {agenta-0.1.18 → agenta-0.1.19}/agenta/cli/main.py +7 -1
  3. {agenta-0.1.18 → agenta-0.1.19}/agenta/cli/variant_commands.py +21 -1
  4. {agenta-0.1.18 → agenta-0.1.19}/agenta/client/client.py +59 -24
  5. {agenta-0.1.18 → agenta-0.1.19}/agenta/docker/docker_utils.py +28 -6
  6. {agenta-0.1.18 → agenta-0.1.19}/pyproject.toml +1 -1
  7. {agenta-0.1.18 → agenta-0.1.19}/README.md +0 -0
  8. {agenta-0.1.18 → agenta-0.1.19}/agenta/__init__.py +0 -0
  9. {agenta-0.1.18 → agenta-0.1.19}/agenta/cli/helper.py +0 -0
  10. {agenta-0.1.18 → agenta-0.1.19}/agenta/client/Readme.md +0 -0
  11. {agenta-0.1.18 → agenta-0.1.19}/agenta/client/__init__.py +0 -0
  12. {agenta-0.1.18 → agenta-0.1.19}/agenta/client/api_models.py +0 -0
  13. {agenta-0.1.18 → agenta-0.1.19}/agenta/config.py +0 -0
  14. {agenta-0.1.18 → agenta-0.1.19}/agenta/config.toml +0 -0
  15. {agenta-0.1.18 → agenta-0.1.19}/agenta/docker/docker-assets/Dockerfile.template +0 -0
  16. {agenta-0.1.18 → agenta-0.1.19}/agenta/docker/docker-assets/README.md +0 -0
  17. {agenta-0.1.18 → agenta-0.1.19}/agenta/docker/docker-assets/entrypoint.sh +0 -0
  18. {agenta-0.1.18 → agenta-0.1.19}/agenta/docker/docker-assets/main.py +0 -0
  19. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/__init__.py +0 -0
  20. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/agenta.py +0 -0
  21. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/context.py +0 -0
  22. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/init.py +0 -0
  23. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/router.py +0 -0
  24. {agenta-0.1.18 → agenta-0.1.19}/agenta/sdk/types.py +0 -0
  25. {agenta-0.1.18 → agenta-0.1.19}/agenta/templates/simple_prompt/README.md +0 -0
  26. {agenta-0.1.18 → agenta-0.1.19}/agenta/templates/simple_prompt/app.py +0 -0
  27. {agenta-0.1.18 → agenta-0.1.19}/agenta/templates/simple_prompt/env.example +0 -0
  28. {agenta-0.1.18 → agenta-0.1.19}/agenta/templates/simple_prompt/requirements.txt +0 -0
  29. {agenta-0.1.18 → agenta-0.1.19}/agenta/templates/simple_prompt/template.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: agenta
3
- Version: 0.1.18
3
+ Version: 0.1.19
4
4
  Summary: Code for the SDK and CLI for the Agenta Lab platform
5
5
  Author: Mahmoud Mabrouk
6
6
  Author-email: mahmoudmabrouk.mail@gmail.com
@@ -37,7 +37,7 @@ def init(app_name: str):
37
37
  if not app_name:
38
38
  while True:
39
39
  app_name = questionary.text('Please enter the app name').ask()
40
- if app_name and re.match('^[a-zA-Z0-9_]+$', app_name):
40
+ if app_name and re.match('^[a-zA-Z0-9_-]+$', app_name):
41
41
  break
42
42
  else:
43
43
  if app_name is None: # User pressed Ctrl+C
@@ -93,6 +93,12 @@ def init(app_name: str):
93
93
  shutil.copy(file, current_dir / file.name)
94
94
  elif init_option is None: # User pressed Ctrl+C
95
95
  sys.exit(0)
96
+
97
+ # Create a .gitignore file and add some default environment folder names to it
98
+ gitignore_content = "# Environments \nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/"
99
+ with open('.gitignore', 'w') as gitignore_file:
100
+ gitignore_file.write(gitignore_content)
101
+
96
102
  click.echo("App initialized successfully")
97
103
  if init_option == 'Start from template':
98
104
  click.echo("Please check the README.md for further instructions to setup the template.")
@@ -1,3 +1,4 @@
1
+ import re
1
2
  import sys
2
3
  from pathlib import Path
3
4
  from typing import List
@@ -41,6 +42,7 @@ def add_variant(variant_name: str, app_folder: str, file_name: str, host: str) -
41
42
  if not app_file.exists():
42
43
  click.echo(click.style(f"No {file_name} exists! Please make sure you are in the right directory", fg='red'))
43
44
  return None
45
+
44
46
  env_file = app_path / '.env'
45
47
  if not env_file.exists():
46
48
  continue_without_env = questionary.confirm(
@@ -48,9 +50,27 @@ def add_variant(variant_name: str, app_folder: str, file_name: str, host: str) -
48
50
  if not continue_without_env:
49
51
  click.echo("Operation cancelled.")
50
52
  sys.exit(0)
53
+
54
+ requirements_file = app_path / 'requirements.txt'
55
+ if not requirements_file.exists():
56
+ continue_without_requirements = questionary.confirm(
57
+ 'No requirements.txt file found! Are you sure you do not need it in your application?\n Do you want to continue without it?').ask()
58
+ if not continue_without_requirements:
59
+ click.echo("Operation cancelled.")
60
+ sys.exit(0)
51
61
 
62
+ # Ask for variant name and validate.
52
63
  if not variant_name:
53
- variant_name = questionary.text('Please enter the variant name').ask()
64
+ while True:
65
+ variant_name = questionary.text('Please enter the variant name').ask()
66
+ if variant_name and re.match('^[a-zA-Z0-9_]+$', variant_name):
67
+ break
68
+ else:
69
+ if variant_name is None: # User pressed Ctrl+C
70
+ sys.exit(0)
71
+ else:
72
+ print("Invalid input. Please use only alphanumeric characters without spaces.")
73
+
54
74
  # update the config file with the variant names from the backend
55
75
  overwrite = False
56
76
  if variant_name in config['variants']:
@@ -14,7 +14,9 @@ class APIRequestError(Exception):
14
14
  """Exception to be raised when an API request fails."""
15
15
 
16
16
 
17
- def add_variant_to_server(app_name: str, variant_name: str, image: Image, host: str):
17
+ def add_variant_to_server(
18
+ app_name: str, variant_name: str, image: Image, host: str
19
+ ):
18
20
  """Adds a variant to the server.
19
21
 
20
22
  Arguments:
@@ -23,32 +25,41 @@ def add_variant_to_server(app_name: str, variant_name: str, image: Image, host:
23
25
  image_name -- Name of the image
24
26
  """
25
27
  app_variant: AppVariant = AppVariant(
26
- app_name=app_name, variant_name=variant_name)
27
- response = requests.post(f"{host}/{BACKEND_URL_SUFFIX}/app_variant/add/from_image/",
28
- json={"app_variant": app_variant.dict(), "image": image.dict()}, timeout=600)
28
+ app_name=app_name, variant_name=variant_name
29
+ )
30
+ response = requests.post(
31
+ f"{host}/{BACKEND_URL_SUFFIX}/app_variant/add/from_image/",
32
+ json={"app_variant": app_variant.dict(), "image": image.dict()},
33
+ timeout=600,
34
+ )
29
35
  if response.status_code != 200:
30
36
  error_message = response.text
31
37
  raise APIRequestError(
32
- f"Request to app_variant endpoint failed with status code {response.status_code} and error message: {error_message}.")
38
+ f"Request to app_variant endpoint failed with status code {response.status_code} and error message: {error_message}."
39
+ )
33
40
 
34
41
 
35
42
  def start_variant(app_name: str, variant_name: str, host: str) -> str:
36
43
  """Starts a container with the variant an expose its endpoint
37
44
 
38
45
  Arguments:
39
- app_name --
46
+ app_name --
40
47
  variant_name -- _description_
41
48
 
42
49
  Returns:
43
50
  The endpoint of the container
44
51
  """
45
- response = requests.post(f"{host}/{BACKEND_URL_SUFFIX}/app_variant/start/",
46
- json={"app_name": app_name, "variant_name": variant_name}, timeout=600)
52
+ response = requests.post(
53
+ f"{host}/{BACKEND_URL_SUFFIX}/app_variant/start/",
54
+ json={"app_name": app_name, "variant_name": variant_name},
55
+ timeout=600,
56
+ )
47
57
  if response.status_code != 200:
48
58
  error_message = response.text
49
59
  raise APIRequestError(
50
- f"Request to start variant endpoint failed with status code {response.status_code} and error message: {error_message}.")
51
- return response.json()['uri']
60
+ f"Request to start variant endpoint failed with status code {response.status_code} and error message: {error_message}."
61
+ )
62
+ return response.json()["uri"]
52
63
 
53
64
 
54
65
  def list_variants(app_name: str, host: str) -> List[AppVariant]:
@@ -60,13 +71,17 @@ def list_variants(app_name: str, host: str) -> List[AppVariant]:
60
71
  Returns:
61
72
  a list of the variants using the pydantic model
62
73
  """
63
- response = requests.get(f"{host}/{BACKEND_URL_SUFFIX}/app_variant/list_variants/?app_name={app_name}", timeout=600)
74
+ response = requests.get(
75
+ f"{host}/{BACKEND_URL_SUFFIX}/app_variant/list_variants/?app_name={app_name}",
76
+ timeout=600,
77
+ )
64
78
 
65
79
  # Check for successful request
66
80
  if response.status_code != 200:
67
81
  error_message = response.text
68
82
  raise APIRequestError(
69
- f"Request to list_variants endpoint failed with status code {response.status_code} and error message: {error_message}.")
83
+ f"Request to list_variants endpoint failed with status code {response.status_code} and error message: {error_message}."
84
+ )
70
85
  app_variants = response.json()
71
86
  return [AppVariant(**variant) for variant in app_variants]
72
87
 
@@ -80,17 +95,24 @@ def remove_variant(app_name: str, variant_name: str, host: str):
80
95
  """
81
96
  app_variant = AppVariant(app_name=app_name, variant_name=variant_name)
82
97
  app_variant_json = app_variant.json()
83
- response = requests.delete(f"{host}/{BACKEND_URL_SUFFIX}/app_variant/remove_variant/",
84
- data=app_variant_json, headers={'Content-Type': 'application/json'}, timeout=600)
98
+ response = requests.delete(
99
+ f"{host}/{BACKEND_URL_SUFFIX}/app_variant/remove_variant/",
100
+ data=app_variant_json,
101
+ headers={"Content-Type": "application/json"},
102
+ timeout=600,
103
+ )
85
104
 
86
105
  # Check for successful request
87
106
  if response.status_code != 200:
88
107
  error_message = response.text
89
108
  raise APIRequestError(
90
- f"Request to remove_variant endpoint failed with status code {response.status_code} and error message: {error_message}")
109
+ f"Request to remove_variant endpoint failed with status code {response.status_code} and error message: {error_message}"
110
+ )
91
111
 
92
112
 
93
- def update_variant_image(app_name: str, variant_name: str, image: Image, host: str):
113
+ def update_variant_image(
114
+ app_name: str, variant_name: str, image: Image, host: str
115
+ ):
94
116
  """Adds a variant to the server.
95
117
 
96
118
  Arguments:
@@ -99,25 +121,38 @@ def update_variant_image(app_name: str, variant_name: str, image: Image, host: s
99
121
  image_name -- Name of the image
100
122
  """
101
123
  app_variant: AppVariant = AppVariant(
102
- app_name=app_name, variant_name=variant_name)
103
- response = requests.put(f"{host}/{BACKEND_URL_SUFFIX}/app_variant/update_variant_image/",
104
- json={"app_variant": app_variant.dict(), "image": image.dict()}, timeout=600)
124
+ app_name=app_name, variant_name=variant_name
125
+ )
126
+ response = requests.put(
127
+ f"{host}/{BACKEND_URL_SUFFIX}/app_variant/update_variant_image/",
128
+ json={"app_variant": app_variant.dict(), "image": image.dict()},
129
+ timeout=600,
130
+ )
105
131
  if response.status_code != 200:
106
132
  error_message = response.text
107
133
  raise APIRequestError(
108
- f"Request to update app_variant failed with status code {response.status_code} and error message: {error_message}.")
134
+ f"Request to update app_variant failed with status code {response.status_code} and error message: {error_message}."
135
+ )
109
136
 
110
137
 
111
- def send_docker_tar(app_name: str, variant_name: str, tar_path: Path, host: str) -> Image:
112
- with tar_path.open('rb') as tar_file:
138
+ def send_docker_tar(
139
+ app_name: str, variant_name: str, tar_path: Path, host: str
140
+ ) -> Image:
141
+ with tar_path.open("rb") as tar_file:
113
142
  response = requests.post(
114
143
  f"{host}/{BACKEND_URL_SUFFIX}/containers/build_image/?app_name={app_name}&variant_name={variant_name}",
115
144
  files={
116
- 'tar_file': tar_file,
145
+ "tar_file": tar_file,
117
146
  },
118
- timeout=1200
147
+ timeout=1200,
119
148
  )
120
149
 
150
+ if response.status_code == 500:
151
+ error_msg = "Serving the variant failed. Here's how you can solve the issue:\n"
152
+ error_msg += "- First, make sure that the requirements.txt file has all the dependencies that you need.\n"
153
+ error_msg += "- Second, check the Docker logs for the backend image to see the error when running the Docker container."
154
+ raise Exception(error_msg)
155
+
121
156
  response.raise_for_status()
122
157
  image = Image.parse_obj(response.json())
123
158
  return image
@@ -1,5 +1,4 @@
1
1
  import logging
2
- import os
3
2
  import shutil
4
3
  import tarfile
5
4
  import tempfile
@@ -40,22 +39,45 @@ def build_tar_docker_container(folder: Path, file_name: Path) -> Path:
40
39
  tarfile_path = folder / "docker.tar.gz" # output file
41
40
  if tarfile_path.exists():
42
41
  tarfile_path.unlink()
42
+
43
43
  dockerfile_path = create_dockerfile(folder)
44
44
  shutil.copytree(Path(__file__).parent.parent / "sdk", folder / "agenta", dirs_exist_ok=True)
45
45
  shutil.copy(Path(__file__).parent /
46
46
  "docker-assets" / "main.py", folder)
47
47
  shutil.copy(Path(__file__).parent /
48
48
  "docker-assets" / "entrypoint.sh", folder)
49
- # tar the directory
49
+
50
+ # Read the contents of .gitignore file
51
+ gitignore_content = ""
52
+ gitignore_file_path = folder / ".gitignore"
53
+ if gitignore_file_path.exists():
54
+ with open(gitignore_file_path, 'r') as gitignore_file:
55
+ gitignore_content = gitignore_file.read()
56
+
57
+ # Create a temporary directory
50
58
  with tempfile.TemporaryDirectory() as temp_dir:
51
59
  temp_path = Path(temp_dir)
52
- shutil.copytree(folder, temp_path, dirs_exist_ok=True)
53
- if (temp_path / "_app.py").exists():
54
- raise ValueError(
55
- "File _app.py already exists in the temp folder. You are not allowed to use this name in your code.")
60
+
61
+ # Clean - remove '/' from every files and folders in the gitignore contents
62
+ sanitized_patterns = [
63
+ pattern.replace("/", "")
64
+ for pattern in gitignore_content.splitlines()
65
+ ]
66
+
67
+ # Function to ignore files based on the patterns
68
+ def ignore_patterns(path, names):
69
+ return set(sanitized_patterns)
70
+
71
+ # Use a single copytree call with ignore_patterns
72
+ shutil.copytree(folder, temp_path, ignore=ignore_patterns, dirs_exist_ok=True)
73
+
74
+ # Rename the specified file to _app.py in the temporary directory
56
75
  shutil.copy(temp_path / file_name, temp_path / "_app.py")
76
+
77
+ # Create the tar.gz file
57
78
  with tarfile.open(tarfile_path, "w:gz") as tar:
58
79
  tar.add(temp_path, arcname=folder.name)
80
+
59
81
  # dockerfile_path.unlink()
60
82
  return tarfile_path
61
83
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "agenta"
3
- version = "0.1.18"
3
+ version = "0.1.19"
4
4
  description = "Code for the SDK and CLI for the Agenta Lab platform"
5
5
  authors = ["Mahmoud Mabrouk <mahmoudmabrouk.mail@gmail.com>"]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes