llamactl 0.3.0a20__py3-none-any.whl → 0.3.0a21__py3-none-any.whl
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.
- llama_deploy/cli/commands/auth.py +23 -13
- llama_deploy/cli/commands/deployment.py +18 -17
- llama_deploy/cli/commands/env.py +19 -14
- llama_deploy/cli/commands/init.py +137 -34
- llama_deploy/cli/commands/serve.py +4 -3
- llama_deploy/cli/env.py +2 -1
- llama_deploy/cli/styles.py +10 -0
- {llamactl-0.3.0a20.dist-info → llamactl-0.3.0a21.dist-info}/METADATA +4 -3
- {llamactl-0.3.0a20.dist-info → llamactl-0.3.0a21.dist-info}/RECORD +11 -10
- {llamactl-0.3.0a20.dist-info → llamactl-0.3.0a21.dist-info}/WHEEL +0 -0
- {llamactl-0.3.0a20.dist-info → llamactl-0.3.0a21.dist-info}/entry_points.txt +0 -0
|
@@ -21,6 +21,13 @@ from llama_deploy.cli.auth.client import (
|
|
|
21
21
|
from llama_deploy.cli.config._config import ConfigManager
|
|
22
22
|
from llama_deploy.cli.config.auth_service import AuthService
|
|
23
23
|
from llama_deploy.cli.config.env_service import service
|
|
24
|
+
from llama_deploy.cli.styles import (
|
|
25
|
+
ACTIVE_INDICATOR,
|
|
26
|
+
HEADER_COLOR,
|
|
27
|
+
MUTED_COL,
|
|
28
|
+
PRIMARY_COL,
|
|
29
|
+
WARNING,
|
|
30
|
+
)
|
|
24
31
|
from llama_deploy.core.client.manage_client import (
|
|
25
32
|
ControlPlaneClient,
|
|
26
33
|
)
|
|
@@ -86,7 +93,7 @@ def create_api_key_profile(
|
|
|
86
93
|
projects, auth_svc.env.requires_auth
|
|
87
94
|
)
|
|
88
95
|
if not selected_project_id:
|
|
89
|
-
rprint("[
|
|
96
|
+
rprint(f"[{WARNING}]No project selected[/]")
|
|
90
97
|
return
|
|
91
98
|
|
|
92
99
|
# Create and set profile
|
|
@@ -125,18 +132,21 @@ def list_profiles() -> None:
|
|
|
125
132
|
current = auth_svc.get_current_profile()
|
|
126
133
|
|
|
127
134
|
if not profiles:
|
|
128
|
-
rprint("[
|
|
129
|
-
|
|
135
|
+
rprint(f"[{WARNING}]No profiles found[/]")
|
|
136
|
+
if auth_svc.env.requires_auth:
|
|
137
|
+
rprint("Create one with: [cyan]llamactl auth login[/cyan]")
|
|
138
|
+
else:
|
|
139
|
+
rprint("Create one with: [cyan]llamactl auth token[/cyan]")
|
|
130
140
|
return
|
|
131
141
|
|
|
132
|
-
table = Table(show_edge=False, box=None, header_style="bold
|
|
133
|
-
table.add_column(" Name")
|
|
134
|
-
table.add_column("Active Project", style=
|
|
142
|
+
table = Table(show_edge=False, box=None, header_style=f"bold {HEADER_COLOR}")
|
|
143
|
+
table.add_column(" Name", style=PRIMARY_COL)
|
|
144
|
+
table.add_column("Active Project", style=MUTED_COL)
|
|
135
145
|
|
|
136
146
|
for profile in profiles:
|
|
137
147
|
text = Text()
|
|
138
148
|
if profile == current:
|
|
139
|
-
text.append("* ", style=
|
|
149
|
+
text.append("* ", style=ACTIVE_INDICATOR)
|
|
140
150
|
else:
|
|
141
151
|
text.append(" ")
|
|
142
152
|
text.append(profile.name)
|
|
@@ -183,7 +193,7 @@ def switch_profile(name: str | None, interactive: bool) -> None:
|
|
|
183
193
|
try:
|
|
184
194
|
selected_auth = _select_profile(auth_svc, name, interactive)
|
|
185
195
|
if not selected_auth:
|
|
186
|
-
rprint("[
|
|
196
|
+
rprint(f"[{WARNING}]No profile selected[/]")
|
|
187
197
|
return
|
|
188
198
|
|
|
189
199
|
auth_svc.set_current_profile(selected_auth.name)
|
|
@@ -204,7 +214,7 @@ def delete_profile(name: str | None, interactive: bool) -> None:
|
|
|
204
214
|
auth_svc = service.current_auth_service()
|
|
205
215
|
auth = _select_profile(auth_svc, name, interactive)
|
|
206
216
|
if not auth:
|
|
207
|
-
rprint("[
|
|
217
|
+
rprint(f"[{WARNING}]No profile selected[/]")
|
|
208
218
|
return
|
|
209
219
|
|
|
210
220
|
if asyncio.run(auth_svc.delete_profile(auth.name)):
|
|
@@ -270,7 +280,7 @@ def change_project(project_id: str | None, interactive: bool) -> None:
|
|
|
270
280
|
projects = _list_projects(auth_svc)
|
|
271
281
|
|
|
272
282
|
if not projects:
|
|
273
|
-
rprint("[
|
|
283
|
+
rprint(f"[{WARNING}]No projects found[/]")
|
|
274
284
|
return
|
|
275
285
|
result = questionary.select(
|
|
276
286
|
"Select a project",
|
|
@@ -296,9 +306,9 @@ def change_project(project_id: str | None, interactive: bool) -> None:
|
|
|
296
306
|
)
|
|
297
307
|
name = selected_project.project_name if selected_project else result
|
|
298
308
|
auth_svc.set_project(profile.name, result)
|
|
299
|
-
rprint(f"Set active project to [bold
|
|
309
|
+
rprint(f"Set active project to [bold {PRIMARY_COL}]{name}[/]")
|
|
300
310
|
else:
|
|
301
|
-
rprint("[
|
|
311
|
+
rprint(f"[{WARNING}]No project selected[/]")
|
|
302
312
|
except Exception as e:
|
|
303
313
|
rprint(f"[red]Error: {e}[/red]")
|
|
304
314
|
raise click.Abort()
|
|
@@ -614,7 +624,7 @@ def _select_profile(
|
|
|
614
624
|
profiles = auth_svc.list_profiles()
|
|
615
625
|
|
|
616
626
|
if not profiles:
|
|
617
|
-
rprint("[
|
|
627
|
+
rprint(f"[{WARNING}]No profiles found[/]")
|
|
618
628
|
return None
|
|
619
629
|
|
|
620
630
|
choices = []
|
|
@@ -11,6 +11,7 @@ import asyncio
|
|
|
11
11
|
import click
|
|
12
12
|
import questionary
|
|
13
13
|
from llama_deploy.cli.commands.auth import validate_authenticated_profile
|
|
14
|
+
from llama_deploy.cli.styles import HEADER_COLOR, MUTED_COL, PRIMARY_COL, WARNING
|
|
14
15
|
from llama_deploy.core.schema.deployments import DeploymentUpdate
|
|
15
16
|
from rich import print as rprint
|
|
16
17
|
from rich.table import Table
|
|
@@ -52,15 +53,15 @@ def list_deployments(interactive: bool) -> None:
|
|
|
52
53
|
|
|
53
54
|
if not deployments:
|
|
54
55
|
rprint(
|
|
55
|
-
f"[
|
|
56
|
+
f"[{WARNING}]No deployments found for project {client.project_id}[/]"
|
|
56
57
|
)
|
|
57
58
|
return
|
|
58
59
|
|
|
59
|
-
table = Table(show_edge=False, box=None, header_style="bold
|
|
60
|
-
table.add_column("Name")
|
|
61
|
-
table.add_column("Status", style=
|
|
62
|
-
table.add_column("URL", style=
|
|
63
|
-
table.add_column("Repository", style=
|
|
60
|
+
table = Table(show_edge=False, box=None, header_style=f"bold {HEADER_COLOR}")
|
|
61
|
+
table.add_column("Name", style=PRIMARY_COL)
|
|
62
|
+
table.add_column("Status", style=MUTED_COL)
|
|
63
|
+
table.add_column("URL", style=MUTED_COL)
|
|
64
|
+
table.add_column("Repository", style=MUTED_COL)
|
|
64
65
|
|
|
65
66
|
for deployment in deployments:
|
|
66
67
|
name = deployment.id
|
|
@@ -96,7 +97,7 @@ def get_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
96
97
|
|
|
97
98
|
deployment_id = select_deployment(deployment_id)
|
|
98
99
|
if not deployment_id:
|
|
99
|
-
rprint("[
|
|
100
|
+
rprint(f"[{WARNING}]No deployment selected[/]")
|
|
100
101
|
return
|
|
101
102
|
if interactive:
|
|
102
103
|
monitor_deployment_screen(deployment_id)
|
|
@@ -104,9 +105,9 @@ def get_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
104
105
|
|
|
105
106
|
deployment = asyncio.run(client.get_deployment(deployment_id))
|
|
106
107
|
|
|
107
|
-
table = Table(show_edge=False, box=None, header_style="bold
|
|
108
|
-
table.add_column("Property", style=
|
|
109
|
-
table.add_column("Value")
|
|
108
|
+
table = Table(show_edge=False, box=None, header_style=f"bold {HEADER_COLOR}")
|
|
109
|
+
table.add_column("Property", style=MUTED_COL, justify="right")
|
|
110
|
+
table.add_column("Value", style=PRIMARY_COL)
|
|
110
111
|
|
|
111
112
|
table.add_row("ID", Text(deployment.id))
|
|
112
113
|
table.add_row("Project ID", Text(deployment.project_id))
|
|
@@ -148,7 +149,7 @@ def create_deployment(
|
|
|
148
149
|
# Use interactive creation
|
|
149
150
|
deployment_form = create_deployment_form()
|
|
150
151
|
if deployment_form is None:
|
|
151
|
-
rprint("[
|
|
152
|
+
rprint(f"[{WARNING}]Cancelled[/]")
|
|
152
153
|
return
|
|
153
154
|
|
|
154
155
|
rprint(
|
|
@@ -168,12 +169,12 @@ def delete_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
168
169
|
|
|
169
170
|
deployment_id = select_deployment(deployment_id, interactive=interactive)
|
|
170
171
|
if not deployment_id:
|
|
171
|
-
rprint("[
|
|
172
|
+
rprint(f"[{WARNING}]No deployment selected[/]")
|
|
172
173
|
return
|
|
173
174
|
|
|
174
175
|
if interactive:
|
|
175
176
|
if not confirm_action(f"Delete deployment '{deployment_id}'?"):
|
|
176
|
-
rprint("[
|
|
177
|
+
rprint(f"[{WARNING}]Cancelled[/]")
|
|
177
178
|
return
|
|
178
179
|
|
|
179
180
|
asyncio.run(client.delete_deployment(deployment_id))
|
|
@@ -196,7 +197,7 @@ def edit_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
196
197
|
|
|
197
198
|
deployment_id = select_deployment(deployment_id, interactive=interactive)
|
|
198
199
|
if not deployment_id:
|
|
199
|
-
rprint("[
|
|
200
|
+
rprint(f"[{WARNING}]No deployment selected[/]")
|
|
200
201
|
return
|
|
201
202
|
|
|
202
203
|
# Get current deployment details
|
|
@@ -205,7 +206,7 @@ def edit_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
205
206
|
# Use the interactive edit form
|
|
206
207
|
updated_deployment = edit_deployment_form(current_deployment)
|
|
207
208
|
if updated_deployment is None:
|
|
208
|
-
rprint("[
|
|
209
|
+
rprint(f"[{WARNING}]Cancelled[/]")
|
|
209
210
|
return
|
|
210
211
|
|
|
211
212
|
rprint(
|
|
@@ -227,7 +228,7 @@ def refresh_deployment(deployment_id: str | None, interactive: bool) -> None:
|
|
|
227
228
|
try:
|
|
228
229
|
deployment_id = select_deployment(deployment_id)
|
|
229
230
|
if not deployment_id:
|
|
230
|
-
rprint("[
|
|
231
|
+
rprint(f"[{WARNING}]No deployment selected[/]")
|
|
231
232
|
return
|
|
232
233
|
|
|
233
234
|
# Get current deployment details to show what we're refreshing
|
|
@@ -282,7 +283,7 @@ def select_deployment(
|
|
|
282
283
|
deployments = asyncio.run(client.list_deployments())
|
|
283
284
|
|
|
284
285
|
if not deployments:
|
|
285
|
-
rprint(f"[
|
|
286
|
+
rprint(f"[{WARNING}]No deployments found for project {client.project_id}[/]")
|
|
286
287
|
return None
|
|
287
288
|
|
|
288
289
|
choices = []
|
llama_deploy/cli/commands/env.py
CHANGED
|
@@ -3,6 +3,13 @@ from importlib import metadata as importlib_metadata
|
|
|
3
3
|
import click
|
|
4
4
|
import questionary
|
|
5
5
|
from llama_deploy.cli.config.schema import Environment
|
|
6
|
+
from llama_deploy.cli.styles import (
|
|
7
|
+
ACTIVE_INDICATOR,
|
|
8
|
+
HEADER_COLOR,
|
|
9
|
+
MUTED_COL,
|
|
10
|
+
PRIMARY_COL,
|
|
11
|
+
WARNING,
|
|
12
|
+
)
|
|
6
13
|
from packaging import version as packaging_version
|
|
7
14
|
from rich import print as rprint
|
|
8
15
|
from rich.table import Table
|
|
@@ -32,23 +39,21 @@ def list_environments_cmd() -> None:
|
|
|
32
39
|
current_env = service.get_current_environment()
|
|
33
40
|
|
|
34
41
|
if not envs:
|
|
35
|
-
rprint("[
|
|
42
|
+
rprint(f"[{WARNING}]No environments found[/]")
|
|
36
43
|
return
|
|
37
44
|
|
|
38
|
-
table = Table(show_edge=False, box=None, header_style="bold
|
|
39
|
-
table.add_column(" API URL")
|
|
40
|
-
table.add_column("Requires Auth")
|
|
45
|
+
table = Table(show_edge=False, box=None, header_style=f"bold {HEADER_COLOR}")
|
|
46
|
+
table.add_column(" API URL", style=PRIMARY_COL)
|
|
47
|
+
table.add_column("Requires Auth", style=MUTED_COL)
|
|
41
48
|
|
|
42
49
|
for env in envs:
|
|
43
50
|
text = Text()
|
|
44
51
|
if env == current_env:
|
|
45
|
-
text.append("* ", style=
|
|
52
|
+
text.append("* ", style=ACTIVE_INDICATOR)
|
|
46
53
|
else:
|
|
47
54
|
text.append(" ")
|
|
48
55
|
text.append(env.api_url)
|
|
49
|
-
table.add_row(
|
|
50
|
-
text, Text("true" if env.requires_auth else "false", style="grey46")
|
|
51
|
-
)
|
|
56
|
+
table.add_row(text, Text("true" if env.requires_auth else "false"))
|
|
52
57
|
|
|
53
58
|
console.print(table)
|
|
54
59
|
except Exception as e:
|
|
@@ -70,7 +75,7 @@ def add_environment_cmd(api_url: str | None, interactive: bool) -> None:
|
|
|
70
75
|
"Enter control plane API URL", default=current_env.api_url
|
|
71
76
|
).ask()
|
|
72
77
|
if not entered:
|
|
73
|
-
rprint("[
|
|
78
|
+
rprint(f"[{WARNING}]No environment entered[/]")
|
|
74
79
|
return
|
|
75
80
|
api_url = entered.strip()
|
|
76
81
|
|
|
@@ -102,7 +107,7 @@ def delete_environment_cmd(api_url: str | None, interactive: bool) -> None:
|
|
|
102
107
|
)
|
|
103
108
|
|
|
104
109
|
if not result:
|
|
105
|
-
rprint("[
|
|
110
|
+
rprint(f"[{WARNING}]No environment selected[/]")
|
|
106
111
|
return
|
|
107
112
|
api_url = result.api_url
|
|
108
113
|
|
|
@@ -133,13 +138,13 @@ def switch_environment_cmd(api_url: str | None, interactive: bool) -> None:
|
|
|
133
138
|
"Select environment",
|
|
134
139
|
)
|
|
135
140
|
if not result:
|
|
136
|
-
rprint("[
|
|
141
|
+
rprint(f"[{WARNING}]No environment selected[/]")
|
|
137
142
|
return
|
|
138
143
|
selected_url = result.api_url
|
|
139
144
|
|
|
140
145
|
if not selected_url:
|
|
141
146
|
if interactive:
|
|
142
|
-
rprint("[
|
|
147
|
+
rprint(f"[{WARNING}]No environment selected[/]")
|
|
143
148
|
return
|
|
144
149
|
raise click.ClickException("API URL is required when not interactive")
|
|
145
150
|
|
|
@@ -150,7 +155,7 @@ def switch_environment_cmd(api_url: str | None, interactive: bool) -> None:
|
|
|
150
155
|
try:
|
|
151
156
|
env = service.auto_update_env(env)
|
|
152
157
|
except Exception as e:
|
|
153
|
-
rprint(f"[
|
|
158
|
+
rprint(f"[{WARNING}]Failed to resolve environment: {e}[/]")
|
|
154
159
|
return
|
|
155
160
|
service.current_auth_service().select_any_profile()
|
|
156
161
|
rprint(f"[green]Switched to environment[/green] {env.api_url}")
|
|
@@ -176,7 +181,7 @@ def _maybe_warn_min_version(min_required: str | None) -> None:
|
|
|
176
181
|
try:
|
|
177
182
|
if packaging_version.parse(current) < packaging_version.parse(min_required):
|
|
178
183
|
rprint(
|
|
179
|
-
f"[
|
|
184
|
+
f"[{WARNING}]Warning:[/] This environment requires llamactl >= [bold]{min_required}[/bold], you have [bold]{current}[/bold]."
|
|
180
185
|
)
|
|
181
186
|
except Exception:
|
|
182
187
|
# If packaging is not available or parsing fails, skip strict comparison
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
1
4
|
import os
|
|
2
5
|
import shutil
|
|
3
6
|
import subprocess
|
|
@@ -10,7 +13,11 @@ import questionary
|
|
|
10
13
|
from click.exceptions import Exit
|
|
11
14
|
from llama_deploy.cli.app import app
|
|
12
15
|
from llama_deploy.cli.options import global_options
|
|
16
|
+
from llama_deploy.cli.styles import HEADER_COLOR_HEX
|
|
13
17
|
from rich import print as rprint
|
|
18
|
+
from vibe_llama.scaffold import create_scaffold
|
|
19
|
+
from vibe_llama.scaffold.scaffold import ProjectName
|
|
20
|
+
from vibe_llama.sdk import VibeLlamaStarter
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
@dataclass
|
|
@@ -18,21 +25,82 @@ class TemplateOption:
|
|
|
18
25
|
id: str
|
|
19
26
|
name: str
|
|
20
27
|
description: str
|
|
21
|
-
|
|
28
|
+
source: VibeLlamaTemplate | GithubTemplateRepo
|
|
29
|
+
llama_cloud: bool
|
|
30
|
+
|
|
22
31
|
|
|
32
|
+
@dataclass
|
|
33
|
+
class VibeLlamaTemplate:
|
|
34
|
+
name: ProjectName
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class GithubTemplateRepo:
|
|
39
|
+
url: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
ui_options = [
|
|
25
43
|
TemplateOption(
|
|
26
44
|
id="basic-ui",
|
|
27
45
|
name="Basic UI",
|
|
28
46
|
description="A basic starter workflow with a React Vite UI",
|
|
29
|
-
|
|
47
|
+
source=GithubTemplateRepo(
|
|
48
|
+
url="https://github.com/run-llama/template-workflow-basic-ui"
|
|
49
|
+
),
|
|
50
|
+
llama_cloud=False,
|
|
30
51
|
),
|
|
31
52
|
TemplateOption(
|
|
32
53
|
id="extraction-review",
|
|
33
54
|
name="Extraction Agent with Review UI",
|
|
34
55
|
description="Extract data from documents using a custom schema and Llama Cloud. Includes a UI to review and correct the results",
|
|
35
|
-
|
|
56
|
+
source=GithubTemplateRepo(
|
|
57
|
+
url="https://github.com/run-llama/template-workflow-data-extraction"
|
|
58
|
+
),
|
|
59
|
+
llama_cloud=True,
|
|
60
|
+
),
|
|
61
|
+
]
|
|
62
|
+
headless_options = [
|
|
63
|
+
TemplateOption(
|
|
64
|
+
id="basic",
|
|
65
|
+
name="Basic Workflow",
|
|
66
|
+
description="A base example that showcases usage patterns for workflows",
|
|
67
|
+
source=VibeLlamaTemplate(name="basic"),
|
|
68
|
+
llama_cloud=False,
|
|
69
|
+
),
|
|
70
|
+
TemplateOption(
|
|
71
|
+
id="document_parsing",
|
|
72
|
+
name="Document Parser",
|
|
73
|
+
description="A workflow that, using LlamaParse, parses unstructured documents and returns their raw text content",
|
|
74
|
+
source=VibeLlamaTemplate(name="document_parsing"),
|
|
75
|
+
llama_cloud=True,
|
|
76
|
+
),
|
|
77
|
+
TemplateOption(
|
|
78
|
+
id="human_in_the_loop",
|
|
79
|
+
name="Human in the Loop",
|
|
80
|
+
description="A workflow showcasing how to use human in the loop with LlamaIndex workflows",
|
|
81
|
+
source=VibeLlamaTemplate(name="human_in_the_loop"),
|
|
82
|
+
llama_cloud=False,
|
|
83
|
+
),
|
|
84
|
+
TemplateOption(
|
|
85
|
+
id="invoice_extraction",
|
|
86
|
+
name="Invoice Extraction",
|
|
87
|
+
description="A workflow that, given an invoice, extracts several key details using LlamaExtract",
|
|
88
|
+
source=VibeLlamaTemplate(name="invoice_extraction"),
|
|
89
|
+
llama_cloud=True,
|
|
90
|
+
),
|
|
91
|
+
TemplateOption(
|
|
92
|
+
id="rag",
|
|
93
|
+
name="RAG",
|
|
94
|
+
description="A workflow that embeds, indexes and queries your documents on the fly, providing you with a simple RAG pipeline",
|
|
95
|
+
source=VibeLlamaTemplate(name="rag"),
|
|
96
|
+
llama_cloud=False,
|
|
97
|
+
),
|
|
98
|
+
TemplateOption(
|
|
99
|
+
id="web_scraping",
|
|
100
|
+
name="Web Scraping",
|
|
101
|
+
description="A workflow that, given several urls, scrapes and summarizes their content using Google's Gemini API",
|
|
102
|
+
source=VibeLlamaTemplate(name="web_scraping"),
|
|
103
|
+
llama_cloud=False,
|
|
36
104
|
),
|
|
37
105
|
]
|
|
38
106
|
|
|
@@ -45,7 +113,7 @@ options = [
|
|
|
45
113
|
)
|
|
46
114
|
@click.option(
|
|
47
115
|
"--template",
|
|
48
|
-
type=click.Choice([o.id for o in
|
|
116
|
+
type=click.Choice([o.id for o in ui_options]),
|
|
49
117
|
help="The template to use for the new app",
|
|
50
118
|
)
|
|
51
119
|
@click.option(
|
|
@@ -76,12 +144,29 @@ def init(
|
|
|
76
144
|
|
|
77
145
|
def _create(template: str | None, dir: Path | None, force: bool) -> None:
|
|
78
146
|
if template is None:
|
|
147
|
+
rprint(
|
|
148
|
+
"[bold]Select a template to start from.[/bold] Either with javascript frontend UI, or just a python workflow that can be used as an API."
|
|
149
|
+
)
|
|
79
150
|
template = questionary.select(
|
|
80
|
-
"
|
|
81
|
-
choices=[
|
|
151
|
+
"",
|
|
152
|
+
choices=[questionary.Separator("------------ With UI -------------")]
|
|
153
|
+
+ [
|
|
154
|
+
questionary.Choice(title=o.name, value=o.id, description=o.description)
|
|
155
|
+
for o in ui_options
|
|
156
|
+
]
|
|
157
|
+
+ [
|
|
158
|
+
questionary.Separator(" "),
|
|
159
|
+
questionary.Separator("--- Headless Workflows (No UI) ---"),
|
|
160
|
+
]
|
|
161
|
+
+ [
|
|
82
162
|
questionary.Choice(title=o.name, value=o.id, description=o.description)
|
|
83
|
-
for o in
|
|
163
|
+
for o in headless_options
|
|
84
164
|
],
|
|
165
|
+
style=questionary.Style(
|
|
166
|
+
[
|
|
167
|
+
("separator", f"fg:{HEADER_COLOR_HEX}"),
|
|
168
|
+
]
|
|
169
|
+
),
|
|
85
170
|
).ask()
|
|
86
171
|
if template is None:
|
|
87
172
|
rprint("No template selected")
|
|
@@ -94,7 +179,9 @@ def _create(template: str | None, dir: Path | None, force: bool) -> None:
|
|
|
94
179
|
rprint("No directory provided")
|
|
95
180
|
raise Exit(1)
|
|
96
181
|
dir = Path(dir_str)
|
|
97
|
-
resolved_template = next(
|
|
182
|
+
resolved_template: TemplateOption | None = next(
|
|
183
|
+
(o for o in ui_options + headless_options if o.id == template), None
|
|
184
|
+
)
|
|
98
185
|
if resolved_template is None:
|
|
99
186
|
rprint(f"Template {template} not found")
|
|
100
187
|
raise Exit(1)
|
|
@@ -107,35 +194,51 @@ def _create(template: str | None, dir: Path | None, force: bool) -> None:
|
|
|
107
194
|
raise Exit(1)
|
|
108
195
|
else:
|
|
109
196
|
shutil.rmtree(dir, ignore_errors=True)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
197
|
+
|
|
198
|
+
if isinstance(resolved_template.source, GithubTemplateRepo):
|
|
199
|
+
copier.run_copy(
|
|
200
|
+
resolved_template.source.url,
|
|
201
|
+
dir,
|
|
202
|
+
quiet=True,
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
asyncio.run(create_scaffold(resolved_template.source.name, str(dir)))
|
|
115
206
|
# Initialize git repository if git is available
|
|
116
|
-
|
|
207
|
+
has_git = False
|
|
117
208
|
try:
|
|
118
209
|
subprocess.run(["git", "--version"], check=True, capture_output=True)
|
|
210
|
+
has_git = True
|
|
211
|
+
except subprocess.CalledProcessError:
|
|
212
|
+
pass
|
|
119
213
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
try:
|
|
125
|
-
subprocess.run(["git", "init"], check=True, capture_output=True)
|
|
126
|
-
subprocess.run(["git", "add", "."], check=True, capture_output=True)
|
|
127
|
-
subprocess.run(
|
|
128
|
-
["git", "commit", "-m", "Initial commit"],
|
|
129
|
-
check=True,
|
|
130
|
-
capture_output=True,
|
|
131
|
-
)
|
|
132
|
-
is_git_initialized = True
|
|
133
|
-
finally:
|
|
134
|
-
os.chdir(original_cwd)
|
|
214
|
+
# Change to the new directory and initialize git repo
|
|
215
|
+
original_cwd = Path.cwd()
|
|
216
|
+
os.chdir(dir)
|
|
135
217
|
|
|
136
|
-
|
|
137
|
-
#
|
|
138
|
-
|
|
218
|
+
try:
|
|
219
|
+
# Dump in a bunch of docs for AI agents
|
|
220
|
+
vibe_llama_starter = VibeLlamaStarter(
|
|
221
|
+
agents=["OpenAI Codex CLI"], # AGENTS.md, supported by Cursor,
|
|
222
|
+
services=["LlamaIndex", "llama-index-workflows"]
|
|
223
|
+
+ (["LlamaCloud Services"] if resolved_template.llama_cloud else []),
|
|
224
|
+
)
|
|
225
|
+
asyncio.run(vibe_llama_starter.write_instructions(overwrite=True))
|
|
226
|
+
# Create symlink for Claude.md to point to AGENTS.md
|
|
227
|
+
for alternate in ["CLAUDE.md", "GEMINI.md"]: # don't support AGENTS.md (yet?)
|
|
228
|
+
claude_path = Path(alternate) # not supported yet
|
|
229
|
+
agents_path = Path("AGENTS.md")
|
|
230
|
+
if agents_path.exists() and not claude_path.exists():
|
|
231
|
+
claude_path.symlink_to("AGENTS.md")
|
|
232
|
+
if has_git:
|
|
233
|
+
subprocess.run(["git", "init"], check=True, capture_output=True)
|
|
234
|
+
subprocess.run(["git", "add", "."], check=True, capture_output=True)
|
|
235
|
+
subprocess.run(
|
|
236
|
+
["git", "commit", "-m", "Initial commit"],
|
|
237
|
+
check=True,
|
|
238
|
+
capture_output=True,
|
|
239
|
+
)
|
|
240
|
+
finally:
|
|
241
|
+
os.chdir(original_cwd)
|
|
139
242
|
|
|
140
243
|
rprint(
|
|
141
244
|
f"Successfully created [blue]{dir}[/] using the [blue]{resolved_template.name}[/] template! 🎉 🦙 💾"
|
|
@@ -146,7 +249,7 @@ def _create(template: str | None, dir: Path | None, force: bool) -> None:
|
|
|
146
249
|
rprint(" [orange3]uvx[/] llamactl serve")
|
|
147
250
|
rprint("")
|
|
148
251
|
rprint("[bold]To deploy:[/]")
|
|
149
|
-
if
|
|
252
|
+
if has_git:
|
|
150
253
|
rprint(" [orange3]git[/] init")
|
|
151
254
|
rprint(" [orange3]git[/] add .")
|
|
152
255
|
rprint(" [orange3]git[/] commit -m 'Initial commit'")
|
|
@@ -13,6 +13,7 @@ from llama_deploy.cli.commands.auth import validate_authenticated_profile
|
|
|
13
13
|
from llama_deploy.cli.config.env_service import service
|
|
14
14
|
from llama_deploy.cli.config.schema import Auth
|
|
15
15
|
from llama_deploy.cli.options import interactive_option
|
|
16
|
+
from llama_deploy.cli.styles import WARNING
|
|
16
17
|
from llama_deploy.core.config import DEFAULT_DEPLOYMENT_FILE_PATH
|
|
17
18
|
from llama_deploy.core.deployment_config import (
|
|
18
19
|
read_deployment_config_from_git_root_or_cwd,
|
|
@@ -182,7 +183,7 @@ def _maybe_inject_llama_cloud_credentials(
|
|
|
182
183
|
env = service.get_current_environment()
|
|
183
184
|
if not env.requires_auth:
|
|
184
185
|
rprint(
|
|
185
|
-
"[
|
|
186
|
+
f"[{WARNING}]Warning: This app requires Llama Cloud authentication, and no LLAMA_CLOUD_API_KEY is present. The app may not work.[/]"
|
|
186
187
|
)
|
|
187
188
|
return
|
|
188
189
|
|
|
@@ -204,11 +205,11 @@ def _maybe_inject_llama_cloud_credentials(
|
|
|
204
205
|
_set_env_vars_from_profile(authed)
|
|
205
206
|
return
|
|
206
207
|
rprint(
|
|
207
|
-
"[
|
|
208
|
+
f"[{WARNING}]Warning: No Llama Cloud credentials configured. The app may not work.[/]"
|
|
208
209
|
)
|
|
209
210
|
return
|
|
210
211
|
|
|
211
212
|
# Non-interactive session
|
|
212
213
|
rprint(
|
|
213
|
-
"[
|
|
214
|
+
f"[{WARNING}]Warning: LLAMA_CLOUD_API_KEY is not set and no logged-in profile was found. The app may not work.[/]"
|
|
214
215
|
)
|
llama_deploy/cli/env.py
CHANGED
|
@@ -4,6 +4,7 @@ from io import StringIO
|
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
6
|
from dotenv import dotenv_values
|
|
7
|
+
from llama_deploy.cli.styles import WARNING
|
|
7
8
|
from rich import print as rprint
|
|
8
9
|
|
|
9
10
|
|
|
@@ -26,6 +27,6 @@ def load_env_secrets_from_string(env_content: str) -> Dict[str, str]:
|
|
|
26
27
|
return {k: str(v) for k, v in secrets.items() if v is not None}
|
|
27
28
|
except Exception as e:
|
|
28
29
|
rprint(
|
|
29
|
-
f"[
|
|
30
|
+
f"[{WARNING}]Warning: Could not parse environment variables from string: {e}[/]"
|
|
30
31
|
)
|
|
31
32
|
return {}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# A place to centralize design tokens to simplify tweaking the appearance of the CLI
|
|
2
|
+
# See https://rich.readthedocs.io/en/stable/appendix/colors.html
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
HEADER_COLOR = "cornflower_blue"
|
|
6
|
+
HEADER_COLOR_HEX = "#5f87ff"
|
|
7
|
+
PRIMARY_COL = "default"
|
|
8
|
+
MUTED_COL = "grey46"
|
|
9
|
+
WARNING = "yellow"
|
|
10
|
+
ACTIVE_INDICATOR = "magenta"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: llamactl
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.0a21
|
|
4
4
|
Summary: A command-line interface for managing LlamaDeploy projects and deployments
|
|
5
5
|
Author: Adrian Lyjak
|
|
6
6
|
Author-email: Adrian Lyjak <adrianlyjak@gmail.com>
|
|
7
7
|
License: MIT
|
|
8
|
-
Requires-Dist: llama-deploy-core[client]>=0.3.
|
|
9
|
-
Requires-Dist: llama-deploy-appserver>=0.3.
|
|
8
|
+
Requires-Dist: llama-deploy-core[client]>=0.3.0a21,<0.4.0
|
|
9
|
+
Requires-Dist: llama-deploy-appserver>=0.3.0a21,<0.4.0
|
|
10
10
|
Requires-Dist: httpx>=0.24.0,<1.0.0
|
|
11
11
|
Requires-Dist: rich>=13.0.0
|
|
12
12
|
Requires-Dist: questionary>=2.0.0
|
|
@@ -17,6 +17,7 @@ Requires-Dist: textual>=6.0.0
|
|
|
17
17
|
Requires-Dist: aiohttp>=3.12.14
|
|
18
18
|
Requires-Dist: copier>=9.9.0
|
|
19
19
|
Requires-Dist: pyjwt[crypto]>=2.10.1
|
|
20
|
+
Requires-Dist: vibe-llama>=0.4.2,<0.5.0
|
|
20
21
|
Requires-Python: >=3.11, <4
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
|
|
@@ -3,11 +3,11 @@ llama_deploy/cli/app.py,sha256=9170e4f506c482522bd745eb1cdb700a198cfcfd7204c168c
|
|
|
3
3
|
llama_deploy/cli/auth/client.py,sha256=0673e2fdc71e8cf1f6d79a64e39596e608dc0257b7dddfebcc38e13e1545a2a8,11670
|
|
4
4
|
llama_deploy/cli/client.py,sha256=f4053b5183224cff55c1393e78887d1af2597219135379a851b742c676adc154,1727
|
|
5
5
|
llama_deploy/cli/commands/aliased_group.py,sha256=bc41007c97b7b93981217dbd4d4591df2b6c9412a2d9ed045b0ec5655ed285f2,1066
|
|
6
|
-
llama_deploy/cli/commands/auth.py,sha256=
|
|
7
|
-
llama_deploy/cli/commands/deployment.py,sha256=
|
|
8
|
-
llama_deploy/cli/commands/env.py,sha256=
|
|
9
|
-
llama_deploy/cli/commands/init.py,sha256=
|
|
10
|
-
llama_deploy/cli/commands/serve.py,sha256=
|
|
6
|
+
llama_deploy/cli/commands/auth.py,sha256=d15d9c234b98f2e7a8c1be1adb111fbae64a2f5bc39b6dd610000a287bf1a132,22141
|
|
7
|
+
llama_deploy/cli/commands/deployment.py,sha256=46339e09135521c46ff90235ccf765c37b1a161cec11d92e92a54ceac6528b01,9883
|
|
8
|
+
llama_deploy/cli/commands/env.py,sha256=36cb1b0abb9e3d1c5546d3e8a3c4c7839c4d6c2abf75763e39efb08376b3eae9,6808
|
|
9
|
+
llama_deploy/cli/commands/init.py,sha256=46f9fcdc43880edbd2f244b4c80d5cc5d387a6f8d7407c182f5995c46e41c851,10153
|
|
10
|
+
llama_deploy/cli/commands/serve.py,sha256=ce08f0ec9c183d4a6f43ee10468b1bbd10edf4af3f2b3311cc1e54c3f4384528,7327
|
|
11
11
|
llama_deploy/cli/config/_config.py,sha256=654a4b6d06542e3503edab7023fc1c3148de510b3e3f6194e28cd4bd3e7c029a,14230
|
|
12
12
|
llama_deploy/cli/config/_migrations.py,sha256=37055641970e1ea41abc583f270dc8a9dab03076224a02cd5fb08bbab2b9259f,2333
|
|
13
13
|
llama_deploy/cli/config/auth_service.py,sha256=8a61110e18c752bbec5fbca23cd5d35d4ec232a4371f8c8291ba07ad83d30c6c,5208
|
|
@@ -17,11 +17,12 @@ llama_deploy/cli/config/migrations/0002_add_auth_fields.sql,sha256=31bd109e5fa0a
|
|
|
17
17
|
llama_deploy/cli/config/migrations/__init__.py,sha256=a092bdd1eba7041e69db0a9594941821a6337018f90d7e231d651195a9db0a69,151
|
|
18
18
|
llama_deploy/cli/config/schema.py,sha256=bd7b68eacd8a242c7f6fbccd176970425eeed504f593838d228a73ea75d73770,1542
|
|
19
19
|
llama_deploy/cli/debug.py,sha256=e85a72d473bbe1645eb31772f7349bde703d45704166f767385895c440afc762,496
|
|
20
|
-
llama_deploy/cli/env.py,sha256=
|
|
20
|
+
llama_deploy/cli/env.py,sha256=d4b83c1f12e07f90893fcc7388d769de37dc2b41d345eb6bc2041c39b4fb2c31,1057
|
|
21
21
|
llama_deploy/cli/interactive_prompts/session_utils.py,sha256=b996f2eddf70d6c49636c4797d246d212fce0950fe7e9a3f59cf6a1bf7ae26f5,1142
|
|
22
22
|
llama_deploy/cli/interactive_prompts/utils.py,sha256=594cc2a242cc3405d66d0e26a60647496cc5fcb4ce7d0500a4cfec4888c9a0fa,516
|
|
23
23
|
llama_deploy/cli/options.py,sha256=62ee7286c3305ddb4b597783d19e854284d79bf9384800045f15b934dc245c1d,1298
|
|
24
24
|
llama_deploy/cli/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
|
25
|
+
llama_deploy/cli/styles.py,sha256=15901fb567b0d10470f56a06d863819c4ed00a9f90b2a8c46b4bc2fb1dbdf6c3,307
|
|
25
26
|
llama_deploy/cli/textual/deployment_form.py,sha256=61ff18bceaba810b40d68aac104969b92870316a7025ba839242c1e0b6bde397,23677
|
|
26
27
|
llama_deploy/cli/textual/deployment_help.py,sha256=91094f9c460421bae75bc705c02c64a9ec464a7e92dd2eb5de365cfd5b08a9a7,2463
|
|
27
28
|
llama_deploy/cli/textual/deployment_monitor.py,sha256=86b2545eeee9ef4ff9c8bec0ee5c8eefd54373d2200da5906a886fb614e763cd,16723
|
|
@@ -30,7 +31,7 @@ llama_deploy/cli/textual/github_callback_server.py,sha256=3111cc45b3ff2632255a37
|
|
|
30
31
|
llama_deploy/cli/textual/llama_loader.py,sha256=33cb32a46dd40bcf889c553e44f2672c410e26bd1d4b17aa6cca6d0a5d59c2c4,1468
|
|
31
32
|
llama_deploy/cli/textual/secrets_form.py,sha256=df6699de29d2bc2cbcaddd41ad2495ce0e622cdccaadbc8369a6ee09a9e79d34,7251
|
|
32
33
|
llama_deploy/cli/textual/styles.tcss,sha256=c8fa0eec00a97fa6907d223faaad82c6add1ea3f60009f1630be19282ea77e3b,3271
|
|
33
|
-
llamactl-0.3.
|
|
34
|
-
llamactl-0.3.
|
|
35
|
-
llamactl-0.3.
|
|
36
|
-
llamactl-0.3.
|
|
34
|
+
llamactl-0.3.0a21.dist-info/WHEEL,sha256=66530aef82d5020ef5af27ae0123c71abb9261377c5bc519376c671346b12918,79
|
|
35
|
+
llamactl-0.3.0a21.dist-info/entry_points.txt,sha256=b67e1eb64305058751a651a80f2d2268b5f7046732268421e796f64d4697f83c,52
|
|
36
|
+
llamactl-0.3.0a21.dist-info/METADATA,sha256=d0896ee39584b3582f370e9e099b1ea5083c53c93f18f5e1c87cad3eb3f0190b,3261
|
|
37
|
+
llamactl-0.3.0a21.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|