llamactl 0.3.0a16__py3-none-any.whl → 0.3.0a18__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.
@@ -276,11 +276,10 @@ def validate_authenticated_profile(interactive: bool) -> Auth:
276
276
 
277
277
 
278
278
  def _prompt_for_api_key() -> str:
279
- while True:
280
- entered = questionary.password("Enter API key token").ask()
281
- if entered:
282
- return entered.strip()
283
- rprint("[yellow]API key is required[/yellow]")
279
+ entered = questionary.password("Enter API key token").ask()
280
+ if entered:
281
+ return entered.strip()
282
+ raise click.ClickException("No API key entered")
284
283
 
285
284
 
286
285
  def _validate_token_and_list_projects(
@@ -1,11 +1,21 @@
1
+ import os
1
2
  from pathlib import Path
2
3
 
3
4
  import click
5
+ import questionary
4
6
  from llama_deploy.appserver.app import (
5
7
  prepare_server,
6
8
  start_server_in_target_venv,
7
9
  )
10
+ from llama_deploy.appserver.workflow_loader import parse_environment_variables
11
+ from llama_deploy.cli.commands.auth import validate_authenticated_profile
12
+ from llama_deploy.cli.config.env_service import service
13
+ from llama_deploy.cli.config.schema import Auth
14
+ from llama_deploy.cli.options import interactive_option
8
15
  from llama_deploy.core.config import DEFAULT_DEPLOYMENT_FILE_PATH
16
+ from llama_deploy.core.deployment_config import (
17
+ read_deployment_config_from_git_root_or_cwd,
18
+ )
9
19
  from rich import print as rprint
10
20
 
11
21
  from ..app import app
@@ -47,6 +57,7 @@ from ..app import app
47
57
  type=click.Choice(["console", "json"], case_sensitive=False),
48
58
  help="The format to use for logging",
49
59
  )
60
+ @interactive_option
50
61
  def serve(
51
62
  deployment_file: Path,
52
63
  no_install: bool,
@@ -57,6 +68,7 @@ def serve(
57
68
  ui_port: int | None = None,
58
69
  log_level: str | None = None,
59
70
  log_format: str | None = None,
71
+ interactive: bool = False,
60
72
  ) -> None:
61
73
  """Run llama_deploy API Server in the foreground. Reads the deployment configuration from the current directory. Can optionally specify a deployment file path."""
62
74
  if not deployment_file.exists():
@@ -64,7 +76,11 @@ def serve(
64
76
  raise click.Abort()
65
77
 
66
78
  try:
79
+ # Pre-check: if the template requires llama cloud access, ensure credentials
80
+ _maybe_inject_llama_cloud_credentials(deployment_file, interactive)
81
+
67
82
  prepare_server(
83
+ deployment_file=deployment_file,
68
84
  install=not no_install,
69
85
  build=preview,
70
86
  )
@@ -86,3 +102,98 @@ def serve(
86
102
  except Exception as e:
87
103
  rprint(f"[red]Error: {e}[/red]")
88
104
  raise click.Abort()
105
+
106
+
107
+ def _set_env_vars_from_profile(profile: Auth):
108
+ if profile.api_key:
109
+ _set_env_vars(profile.api_key, profile.api_url)
110
+
111
+
112
+ def _set_env_vars_from_env(env_vars: dict[str, str]):
113
+ key = env_vars.get("LLAMA_CLOUD_API_KEY")
114
+ url = env_vars.get("LLAMA_CLOUD_BASE_URL", "https://api.cloud.llamaindex.ai")
115
+ if key:
116
+ _set_env_vars(key, url)
117
+
118
+
119
+ def _set_env_vars(key: str, url: str):
120
+ print(f"Setting env vars: {key}, {url}")
121
+ os.environ["LLAMA_CLOUD_API_KEY"] = key
122
+ os.environ["LLAMA_CLOUD_BASE_URL"] = url
123
+ # kludge for common web servers to inject local auth key
124
+ for prefix in ["VITE_", "NEXT_PUBLIC_"]:
125
+ os.environ[f"{prefix}LLAMA_CLOUD_API_KEY"] = key
126
+ os.environ[f"{prefix}LLAMA_CLOUD_BASE_URL"] = url
127
+
128
+
129
+ def _maybe_inject_llama_cloud_credentials(
130
+ deployment_file: Path, interactive: bool
131
+ ) -> None:
132
+ """If the deployment config indicates Llama Cloud usage, ensure LLAMA_CLOUD_API_KEY is set.
133
+
134
+ Behavior:
135
+ - If LLAMA_CLOUD_API_KEY is already set, do nothing.
136
+ - Else, try to read current profile's api_key and inject.
137
+ - If no profile/api_key and session is interactive, prompt to log in and inject afterward.
138
+ - If user declines or session is non-interactive, warn that deployment may not work.
139
+ """
140
+ # Read config directly to avoid cached global settings
141
+ try:
142
+ config = read_deployment_config_from_git_root_or_cwd(
143
+ Path.cwd(), deployment_file
144
+ )
145
+ except Exception:
146
+ rprint(
147
+ "[red]Error: Could not read a deployment config. This doesn't appear to be a valid llama-deploy project.[/red]"
148
+ )
149
+ raise click.Abort()
150
+
151
+ if not config.llama_cloud:
152
+ return
153
+
154
+ vars = parse_environment_variables(
155
+ config, deployment_file.parent if deployment_file.is_file() else deployment_file
156
+ )
157
+
158
+ existing = os.environ.get("LLAMA_CLOUD_API_KEY") or vars.get("LLAMA_CLOUD_API_KEY")
159
+ if existing:
160
+ _set_env_vars_from_env({**os.environ, **vars})
161
+ return
162
+
163
+ env = service.get_current_environment()
164
+ if not env.requires_auth:
165
+ rprint(
166
+ "[yellow]Warning: This app requires Llama Cloud authentication, and no LLAMA_CLOUD_API_KEY is present. The app may not work.[/yellow]"
167
+ )
168
+ return
169
+
170
+ auth_svc = service.current_auth_service()
171
+ profile = auth_svc.get_current_profile()
172
+ if profile and profile.api_key:
173
+ _set_env_vars_from_profile(profile)
174
+ return
175
+
176
+ # No key available; consider prompting if interactive
177
+ if interactive:
178
+ should_login = questionary.confirm(
179
+ "This deployment requires Llama Cloud. Login now to inject credentials?",
180
+ default=True,
181
+ ).ask()
182
+ if should_login:
183
+ try:
184
+ authed = validate_authenticated_profile(True)
185
+ if authed.api_key:
186
+ _set_env_vars_from_profile(authed)
187
+ return
188
+ except Exception:
189
+ # fall through to warning
190
+ pass
191
+ rprint(
192
+ "[yellow]Warning: No Llama Cloud credentials configured. The app may not work.[/yellow]"
193
+ )
194
+ return
195
+
196
+ # Non-interactive session
197
+ rprint(
198
+ "[yellow]Warning: LLAMA_CLOUD_API_KEY is not set and no logged-in profile was found. The deployment may not work.[/yellow]"
199
+ )
@@ -79,13 +79,40 @@ class ConfigManager:
79
79
  if "api_key" not in mig_columns:
80
80
  conn.execute("ALTER TABLE profiles ADD COLUMN api_key TEXT")
81
81
 
82
+ # Migration: change profiles primary key from name to composite (name, api_url)
83
+ # Only perform if the table exists with single-column PK on name
84
+ pk_info_cur = conn.execute("PRAGMA table_info(profiles)")
85
+ pk_info_rows = pk_info_cur.fetchall()
86
+ pk_columns = [row[1] for row in pk_info_rows if len(row) > 5 and row[5] > 0]
87
+ if pk_columns == ["name"] and "api_url" in columns:
88
+ conn.execute("ALTER TABLE profiles RENAME TO profiles_old")
89
+ conn.execute(
90
+ """
91
+ CREATE TABLE profiles (
92
+ name TEXT NOT NULL,
93
+ api_url TEXT NOT NULL,
94
+ project_id TEXT NOT NULL,
95
+ api_key TEXT,
96
+ PRIMARY KEY (name, api_url)
97
+ )
98
+ """
99
+ )
100
+ conn.execute(
101
+ """
102
+ INSERT INTO profiles (name, api_url, project_id, api_key)
103
+ SELECT name, api_url, project_id, api_key FROM profiles_old
104
+ """
105
+ )
106
+ conn.execute("DROP TABLE profiles_old")
107
+
82
108
  # Create tables with new schema (this will only create if they don't exist)
83
109
  conn.execute("""
84
110
  CREATE TABLE IF NOT EXISTS profiles (
85
- name TEXT PRIMARY KEY,
111
+ name TEXT NOT NULL,
86
112
  api_url TEXT NOT NULL,
87
113
  project_id TEXT NOT NULL,
88
- api_key TEXT
114
+ api_key TEXT,
115
+ PRIMARY KEY (name, api_url)
89
116
  )
90
117
  """)
91
118
 
@@ -177,7 +204,9 @@ class ConfigManager:
177
204
  )
178
205
  conn.commit()
179
206
  except sqlite3.IntegrityError:
180
- raise ValueError(f"Profile '{name}' already exists")
207
+ raise ValueError(
208
+ f"Profile '{name}' already exists for environment '{api_url}'"
209
+ )
181
210
 
182
211
  return profile
183
212
 
@@ -64,5 +64,5 @@ def _auto_profile_name_from_token(api_key: str) -> str:
64
64
  cleaned = token.replace(" ", "")
65
65
  first = cleaned[:6]
66
66
  last = cleaned[-4:] if len(cleaned) > 10 else cleaned[-2:]
67
- base = f"token-{first}-{last}"
67
+ base = f"{first}****{last}"
68
68
  return base
@@ -30,6 +30,8 @@ class EnvService:
30
30
  self.config_manager.create_or_update_environment(
31
31
  env.api_url, env.requires_auth, env.min_llamactl_version
32
32
  )
33
+ self.config_manager.set_settings_current_environment(env.api_url)
34
+ self.config_manager.set_settings_current_profile(None)
33
35
 
34
36
  def delete_environment(self, api_url: str) -> bool:
35
37
  return self.config_manager.delete_environment(api_url)
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: llamactl
3
- Version: 0.3.0a16
3
+ Version: 0.3.0a18
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.0a16,<0.4.0
9
- Requires-Dist: llama-deploy-appserver>=0.3.0a16,<0.4.0
10
- Requires-Dist: httpx>=0.24.0
8
+ Requires-Dist: llama-deploy-core[client]>=0.3.0a18,<0.4.0
9
+ Requires-Dist: llama-deploy-appserver>=0.3.0a18,<0.4.0
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
13
13
  Requires-Dist: click>=8.2.1
@@ -2,14 +2,14 @@ llama_deploy/cli/__init__.py,sha256=df028686233c4d5a3e244bb50c1c7b84cf2399ae03ab
2
2
  llama_deploy/cli/app.py,sha256=9170e4f506c482522bd745eb1cdb700a198cfcfd7204c168c94e5ee2b6b43ffa,2199
3
3
  llama_deploy/cli/client.py,sha256=f0f72c90cddfbc9198e154883f3b8f05fb47dbe7ec1f5755106dbb8009d2bb54,1459
4
4
  llama_deploy/cli/commands/aliased_group.py,sha256=bc41007c97b7b93981217dbd4d4591df2b6c9412a2d9ed045b0ec5655ed285f2,1066
5
- llama_deploy/cli/commands/auth.py,sha256=de584d11c1acf5a4e7aee8c8f30184335053ed206d38dbc8509b2d1d0677a092,12640
5
+ llama_deploy/cli/commands/auth.py,sha256=da8ad888a199955b8c970e84e6933c92211a1c823e77ec6d746ed994e09c7adf,12610
6
6
  llama_deploy/cli/commands/deployment.py,sha256=ae6e20c216edf51df94cd66397743076bb97ee2b64bccd14e602e9642fe6befd,9980
7
7
  llama_deploy/cli/commands/env.py,sha256=e0b96b9f4e7921b4370ad5f8bc0a2bfb19b705e73004f72c37c9bed28a208e0d,6702
8
8
  llama_deploy/cli/commands/init.py,sha256=51b2de1e35ff34bc15c9dfec72fbad08aaf528c334df168896d36458a4e9401c,6307
9
- llama_deploy/cli/commands/serve.py,sha256=4d47850397ba172944df56a934a51bedb52403cbd3f9b000b1ced90a31c75049,2721
10
- llama_deploy/cli/config/_config.py,sha256=31376c3f3ecadaf52545e4aeb4a660dde2c22d7e6c33b232ec93eebeb926e3fb,14953
11
- llama_deploy/cli/config/auth_service.py,sha256=38a2de9bbcf5780675130d90e4f9116da190fd31a33e1c178a7f3847b943c229,2667
12
- llama_deploy/cli/config/env_service.py,sha256=6e50ffe2e33dcff4193c87b3df8daac71542d406314a7bcaf48187715a53780e,2445
9
+ llama_deploy/cli/commands/serve.py,sha256=1841c9c63fdd6616b28f36ab899582bfd5b513ed77f3d176e99ccaa8bdd7944a,6775
10
+ llama_deploy/cli/config/_config.py,sha256=91caae934d27f2b956156a4e9f5df151692786e139e7e13611961df0dd67a3b5,16287
11
+ llama_deploy/cli/config/auth_service.py,sha256=d1c978e1249276285db7aa7b490ca3f6d06e892c0cb171bdbe08799fe55d1d40,2664
12
+ llama_deploy/cli/config/env_service.py,sha256=d8583b1632aec33c74bfe62fa5f3489161dbc00edbfb317f24907a0bc8ac671b,2582
13
13
  llama_deploy/cli/config/schema.py,sha256=086b6161b238c2037068a2b510f5d4bbda917494df764818ff9692e9735a8953,608
14
14
  llama_deploy/cli/debug.py,sha256=e85a72d473bbe1645eb31772f7349bde703d45704166f767385895c440afc762,496
15
15
  llama_deploy/cli/env.py,sha256=6ebc24579815b3787829c81fd5bb9f31698a06e62c0128a788559f962b33a7af,1016
@@ -26,7 +26,7 @@ llama_deploy/cli/textual/github_callback_server.py,sha256=dc74c510f8a98ef6ffaab0
26
26
  llama_deploy/cli/textual/llama_loader.py,sha256=33cb32a46dd40bcf889c553e44f2672c410e26bd1d4b17aa6cca6d0a5d59c2c4,1468
27
27
  llama_deploy/cli/textual/secrets_form.py,sha256=a43fbd81aad034d0d60906bfd917c107f9ace414648b0f63ac0b29eeba4050db,7061
28
28
  llama_deploy/cli/textual/styles.tcss,sha256=b1a54dc5fb0e0aa12cbf48807e9e6a94b9926838b8058dae1336a134f02e92b0,3327
29
- llamactl-0.3.0a16.dist-info/WHEEL,sha256=66530aef82d5020ef5af27ae0123c71abb9261377c5bc519376c671346b12918,79
30
- llamactl-0.3.0a16.dist-info/entry_points.txt,sha256=b67e1eb64305058751a651a80f2d2268b5f7046732268421e796f64d4697f83c,52
31
- llamactl-0.3.0a16.dist-info/METADATA,sha256=f3383216d44bc4e4bd19e7589cac4e4e24918f513ad9d2b46498f4848a380047,3177
32
- llamactl-0.3.0a16.dist-info/RECORD,,
29
+ llamactl-0.3.0a18.dist-info/WHEEL,sha256=66530aef82d5020ef5af27ae0123c71abb9261377c5bc519376c671346b12918,79
30
+ llamactl-0.3.0a18.dist-info/entry_points.txt,sha256=b67e1eb64305058751a651a80f2d2268b5f7046732268421e796f64d4697f83c,52
31
+ llamactl-0.3.0a18.dist-info/METADATA,sha256=a7089a1d4aac69fdc32c230ea89700ec038b320d8a8e297c908bf01b3c7ede2a,3184
32
+ llamactl-0.3.0a18.dist-info/RECORD,,