llamactl 0.3.17__tar.gz → 0.3.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.
Files changed (44) hide show
  1. {llamactl-0.3.17 → llamactl-0.3.19}/PKG-INFO +3 -3
  2. {llamactl-0.3.17 → llamactl-0.3.19}/pyproject.toml +3 -3
  3. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/aliased_group.py +2 -2
  4. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/auth.py +22 -3
  5. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/deployment_form.py +19 -7
  6. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/deployment_monitor.py +3 -1
  7. {llamactl-0.3.17 → llamactl-0.3.19}/README.md +0 -0
  8. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/__init__.py +0 -0
  9. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/app.py +0 -0
  10. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/auth/client.py +0 -0
  11. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/client.py +0 -0
  12. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/deployment.py +0 -0
  13. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/env.py +0 -0
  14. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/init.py +0 -0
  15. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/pkg.py +0 -0
  16. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/commands/serve.py +0 -0
  17. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/_config.py +0 -0
  18. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/_migrations.py +0 -0
  19. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/auth_service.py +0 -0
  20. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/env_service.py +0 -0
  21. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/migrations/0001_init.sql +0 -0
  22. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/migrations/0002_add_auth_fields.sql +0 -0
  23. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/migrations/__init__.py +0 -0
  24. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/config/schema.py +0 -0
  25. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/debug.py +0 -0
  26. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/env.py +0 -0
  27. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/interactive_prompts/session_utils.py +0 -0
  28. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/interactive_prompts/utils.py +0 -0
  29. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/options.py +0 -0
  30. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/pkg/__init__.py +0 -0
  31. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/pkg/defaults.py +0 -0
  32. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/pkg/options.py +0 -0
  33. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/pkg/utils.py +0 -0
  34. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/py.typed +0 -0
  35. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/styles.py +0 -0
  36. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/deployment_help.py +0 -0
  37. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/git_validation.py +0 -0
  38. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/github_callback_server.py +0 -0
  39. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/llama_loader.py +0 -0
  40. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/secrets_form.py +0 -0
  41. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/textual/styles.tcss +0 -0
  42. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/utils/env_inject.py +0 -0
  43. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/utils/redact.py +0 -0
  44. {llamactl-0.3.17 → llamactl-0.3.19}/src/llama_deploy/cli/utils/version.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: llamactl
3
- Version: 0.3.17
3
+ Version: 0.3.19
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.17,<0.4.0
9
- Requires-Dist: llama-deploy-appserver>=0.3.17,<0.4.0
8
+ Requires-Dist: llama-deploy-core[client]>=0.3.19,<0.4.0
9
+ Requires-Dist: llama-deploy-appserver>=0.3.19,<0.4.0
10
10
  Requires-Dist: vibe-llama-core>=0.1.0
11
11
  Requires-Dist: rich>=13.0.0
12
12
  Requires-Dist: questionary>=2.0.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "llamactl"
3
- version = "0.3.17"
3
+ version = "0.3.19"
4
4
  description = "A command-line interface for managing LlamaDeploy projects and deployments"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -9,8 +9,8 @@ authors = [
9
9
  ]
10
10
  requires-python = ">=3.11, <4"
11
11
  dependencies = [
12
- "llama-deploy-core[client]>=0.3.17,<0.4.0",
13
- "llama-deploy-appserver>=0.3.17,<0.4.0",
12
+ "llama-deploy-core[client]>=0.3.19,<0.4.0",
13
+ "llama-deploy-appserver>=0.3.19,<0.4.0",
14
14
  "vibe-llama-core>=0.1.0",
15
15
  "rich>=13.0.0",
16
16
  "questionary>=2.0.0",
@@ -27,7 +27,7 @@ class AliasedGroup(click.Group):
27
27
 
28
28
  def resolve_command(
29
29
  self, ctx: click.Context, args: list[str]
30
- ) -> tuple[str, click.Command, list[str]]:
30
+ ) -> tuple[str | None, click.Command | None, list[str]]:
31
31
  # always return the full command name
32
32
  _, cmd, args = super().resolve_command(ctx, args)
33
- return cmd.name, cmd, args
33
+ return cmd.name if cmd else None, cmd, args
@@ -44,6 +44,11 @@ from ..config.schema import Auth, DeviceOIDC
44
44
  from ..options import global_options, interactive_option
45
45
 
46
46
 
47
+ # Specific auth/login flow exceptions
48
+ class NoProjectsFoundError(Exception):
49
+ """Raised when the authenticated user has no accessible projects."""
50
+
51
+
47
52
  # Create sub-applications for organizing commands
48
53
  @app.group(
49
54
  help="Login to llama cloud control plane to manage deployments",
@@ -120,6 +125,15 @@ def device_login() -> None:
120
125
  f"[green]Created login profile '{created.name}' and set as current[/green]"
121
126
  )
122
127
 
128
+ except NoProjectsFoundError:
129
+ # Friendly guidance for first-time users with no projects
130
+ rprint(f"[{WARNING}]⚠️ No Existing Projects - Welcome to LlamaCloud![/]")
131
+ rprint(f"[{WARNING}]Looks like this may be your first time logging in.[/]")
132
+ rprint(
133
+ f"[{WARNING}]Before you can get started, log in to https://cloud.llamaindex.ai to complete your account setup.[/]"
134
+ )
135
+ return
136
+
123
137
  except Exception as e:
124
138
  rprint(f"[red]Error: {e}[/red]")
125
139
  raise click.Abort()
@@ -418,11 +432,14 @@ def _create_device_profile() -> Auth:
418
432
 
419
433
  # Obtain or prompt for project ID and create profile
420
434
  projects = _list_projects(auth_svc, oidc_device.device_access_token)
435
+ if not projects:
436
+ # No projects available for this user yet
437
+ raise NoProjectsFoundError()
438
+
421
439
  selected_project_id = _select_or_enter_project(projects, True)
422
440
  if not selected_project_id:
423
- raise click.ClickException(
424
- "Project is required. Does this user have access to any projects?"
425
- )
441
+ # User cancelled selection despite having projects
442
+ raise click.ClickException("No project selected")
426
443
  created = auth_svc.create_or_update_profile_from_oidc(
427
444
  selected_project_id, oidc_device
428
445
  )
@@ -501,6 +518,8 @@ async def _run_device_authentication(base_url: str) -> DeviceOIDC:
501
518
  raise click.ClickException(
502
519
  "Device flow failed: token response missing access_token"
503
520
  )
521
+ if not provider.jwks_uri:
522
+ raise click.ClickException("Provider does not expose jwks_uri")
504
523
  claims = await decode_jwt_claims(token.id_token, provider.jwks_uri)
505
524
  email = claims.get("email")
506
525
  if not email:
@@ -6,6 +6,7 @@ import re
6
6
  from dataclasses import dataclass, field
7
7
  from pathlib import Path
8
8
  from textwrap import dedent
9
+ from typing import cast
9
10
  from urllib.parse import urlsplit
10
11
 
11
12
  from llama_deploy.cli.client import get_project_client as get_client
@@ -117,7 +118,11 @@ class DeploymentForm:
117
118
  def to_update(self) -> DeploymentUpdate:
118
119
  """Convert form data to API format"""
119
120
 
120
- secrets: dict[str, str | None] = self.secrets.copy()
121
+ secrets: dict[str, str | None] = cast(
122
+ # dict isn't covariant, so whatever, make it work
123
+ dict[str, str | None],
124
+ self.secrets.copy(),
125
+ )
121
126
  for secret in self.removed_secrets:
122
127
  secrets[secret] = None
123
128
 
@@ -287,7 +292,11 @@ class DeploymentFormWidget(Widget):
287
292
  or existing_version
288
293
  or installed_version
289
294
  )
290
- is_upgrade = Version(installed_version) > Version(existing_version)
295
+ is_upgrade = (
296
+ installed_version
297
+ and existing_version
298
+ and Version(installed_version) > Version(existing_version)
299
+ )
291
300
  label = "Upgrade" if is_upgrade else "Downgrade"
292
301
  yield Select(
293
302
  [
@@ -563,11 +572,14 @@ class DeploymentEditApp(App[DeploymentResponse | None]):
563
572
  result = self.form_data
564
573
  client = get_client()
565
574
  try:
566
- update_deployment = (
567
- await client.update_deployment(result.id, result.to_update())
568
- if result.is_editing
569
- else await client.create_deployment(result.to_create())
570
- )
575
+ if result.is_editing:
576
+ if not result.id:
577
+ raise ValueError("Deployment ID is required for update")
578
+ update_deployment = await client.update_deployment(
579
+ result.id, result.to_update()
580
+ )
581
+ else:
582
+ update_deployment = await client.create_deployment(result.to_create())
571
583
  # Save and navigate to embedded monitor screen
572
584
  self.saved_deployment = update_deployment
573
585
  # Ensure form_data carries the new ID for any subsequent operations
@@ -365,7 +365,9 @@ class DeploymentMonitorWidget(Widget):
365
365
  ev_details_widget = self.query_one("#last_event_details", Static)
366
366
  deployment_link_button = self.query_one("#deployment_link_button", Button)
367
367
  widget.update(self._render_status_line())
368
- deployment_link_button.label = f"{str(self.deployment.apiserver_url or '')}"
368
+ deployment_link_button.label = (
369
+ f"{str(self.deployment.apiserver_url or '') if self.deployment else ''}"
370
+ )
369
371
  # Update last event line
370
372
  ev_widget.update(self._render_last_event_status())
371
373
  ev_details_widget.update(self._render_last_event_details())
File without changes