3
3
from typing import Annotated
4
4
5
5
import aiohttp
6
+ import questionary
6
7
import rich
7
8
import typer
8
9
from dotenv import dotenv_values
12
13
from libertai_client .config import config
13
14
from libertai_client .interfaces .agent import AgentPythonPackageManager , AgentUsageType
14
15
from libertai_client .utils .agent import parse_agent_config_env , create_agent_zip
15
- from libertai_client .utils .python import detect_python_project_version
16
+ from libertai_client .utils .python import (
17
+ detect_python_project_version ,
18
+ detect_python_dependencies_management ,
19
+ validate_python_version ,
20
+ )
16
21
from libertai_client .utils .system import get_full_path
17
22
from libertai_client .utils .typer import AsyncTyper
18
23
19
24
app = AsyncTyper (name = "agent" , help = "Deploy and manage agents" )
20
25
21
26
err_console = Console (stderr = True )
22
27
28
+ dependencies_management_choices : list [questionary .Choice ] = [
29
+ questionary .Choice (
30
+ title = "poetry" ,
31
+ value = AgentPythonPackageManager .poetry ,
32
+ description = "poetry-style pyproject.toml and poetry.lock" ,
33
+ ),
34
+ questionary .Choice (
35
+ title = "requirements.txt" ,
36
+ value = AgentPythonPackageManager .pip ,
37
+ description = "Any management tool that outputs a requirements.txt file (pip, pip-tools...)" ,
38
+ ),
39
+ questionary .Choice (
40
+ title = "pyproject.toml" ,
41
+ value = "TODO" ,
42
+ description = "Any tool respecting the standard PEP 621 pyproject.toml (hatch, modern usage of setuptools...)" ,
43
+ disabled = "Coming soon" ,
44
+ ),
45
+ ]
46
+
23
47
24
48
@app .command ()
25
49
async def deploy (
26
50
path : Annotated [str , typer .Argument (help = "Path to the root of your project" )] = "." ,
27
51
python_version : Annotated [
28
52
str | None , typer .Option (help = "Version to deploy with" , prompt = False )
29
53
] = None ,
30
- package_manager : Annotated [
54
+ dependencies_management : Annotated [
31
55
AgentPythonPackageManager | None ,
32
56
typer .Option (
33
57
help = "Package manager used to handle dependencies" ,
@@ -55,23 +79,50 @@ async def deploy(
55
79
err_console .print (f"[red]{ error } " )
56
80
raise typer .Exit (1 )
57
81
58
- # TODO: try to detect package manager, show detected value and ask user for the confirmation or change
59
- if package_manager is None :
60
- package_manager = AgentPythonPackageManager .poetry
82
+ if dependencies_management is None :
83
+ # Trying to find the way dependencies are managed
84
+ detected_dependencies_management = detect_python_dependencies_management (path )
85
+ # Confirming with the user (or asking if none found)
86
+ dependencies_management = await questionary .select (
87
+ "Dependencies management" ,
88
+ choices = dependencies_management_choices ,
89
+ default = next (
90
+ (
91
+ choice
92
+ for choice in dependencies_management_choices
93
+ if choice .value == detected_dependencies_management .value
94
+ ),
95
+ None ,
96
+ ),
97
+ show_description = True ,
98
+ ).ask_async ()
99
+ if dependencies_management is None :
100
+ err_console .print (
101
+ "[red]You must select the way Python dependencies are managed."
102
+ )
103
+ raise typer .Exit (1 )
61
104
62
105
if python_version is None :
63
106
# Trying to find the python version
64
- detected_python_version = detect_python_project_version (path , package_manager )
107
+ detected_python_version = detect_python_project_version (
108
+ path , dependencies_management
109
+ )
65
110
# Confirming the version with the user (or asking if none found)
66
- python_version = typer .prompt ("Python version" , default = detected_python_version )
111
+ python_version = await questionary .text (
112
+ "Python version" ,
113
+ default = detected_python_version
114
+ if detected_python_version is not None
115
+ else "" ,
116
+ validate = validate_python_version ,
117
+ ).ask_async ()
67
118
68
119
agent_zip_path = "/tmp/libertai-agent.zip"
69
120
create_agent_zip (path , agent_zip_path )
70
121
71
122
data = aiohttp .FormData ()
72
123
data .add_field ("secret" , libertai_config .secret )
73
124
data .add_field ("python_version" , python_version )
74
- data .add_field ("package_manager" , package_manager .value )
125
+ data .add_field ("package_manager" , dependencies_management .value )
75
126
data .add_field ("usage_type" , usage_type .value )
76
127
data .add_field ("code" , open (agent_zip_path , "rb" ), filename = "libertai-agent.zip" )
77
128
@@ -83,10 +134,12 @@ async def deploy(
83
134
) as response :
84
135
if response .status == 200 :
85
136
response_data = UpdateAgentResponse (** json .loads (await response .text ())) # noqa: F821
86
- # TODO: don't show /docs if deployed in python mode
87
- rich .print (
88
- f"[green]Agent successfully deployed on http://[{ response_data .instance_ip } ]:8000/docs"
137
+ success_text = (
138
+ f"Agent successfully deployed on http://[{ response_data .instance_ip } ]:8000/docs"
139
+ if usage_type == AgentUsageType .fastapi
140
+ else f"Agent successfully deployed on instance { response_data .instance_ip } "
89
141
)
142
+ rich .print (f"[green]{ success_text } " )
90
143
else :
91
144
error_message = await response .text ()
92
145
err_console .print (f"[red]Request failed\n { error_message } " )
0 commit comments