lightning-sdk 2025.8.6rc2__py3-none-any.whl → 2025.11.5__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.
Files changed (330) hide show
  1. lightning_sdk/__init__.py +13 -7
  2. lightning_sdk/__version__.py +3 -0
  3. lightning_sdk/agents.py +2 -1
  4. lightning_sdk/ai_hub.py +2 -1
  5. lightning_sdk/api/__init__.py +2 -0
  6. lightning_sdk/api/base_studio_api.py +13 -9
  7. lightning_sdk/api/cloud_account_api.py +31 -10
  8. lightning_sdk/api/deployment_api.py +27 -1
  9. lightning_sdk/api/job_api.py +16 -12
  10. lightning_sdk/api/license_api.py +26 -59
  11. lightning_sdk/api/llm_api.py +25 -2
  12. lightning_sdk/api/mmt_api.py +5 -2
  13. lightning_sdk/api/studio_api.py +252 -55
  14. lightning_sdk/api/teamspace_api.py +106 -30
  15. lightning_sdk/api/user_api.py +56 -2
  16. lightning_sdk/api/utils.py +108 -18
  17. lightning_sdk/base_studio.py +51 -27
  18. lightning_sdk/cli/__init__.py +1 -0
  19. lightning_sdk/cli/base_studio/__init__.py +10 -0
  20. lightning_sdk/cli/base_studio/list.py +43 -0
  21. lightning_sdk/cli/config/__init__.py +14 -0
  22. lightning_sdk/cli/config/get.py +57 -0
  23. lightning_sdk/cli/config/set.py +92 -0
  24. lightning_sdk/cli/config/show.py +9 -0
  25. lightning_sdk/cli/entrypoint.py +71 -71
  26. lightning_sdk/cli/groups.py +56 -0
  27. lightning_sdk/cli/job/__init__.py +7 -0
  28. lightning_sdk/cli/{clusters_menu.py → legacy/clusters_menu.py} +9 -6
  29. lightning_sdk/cli/{configure.py → legacy/configure.py} +2 -2
  30. lightning_sdk/cli/{connect.py → legacy/connect.py} +2 -2
  31. lightning_sdk/cli/{create.py → legacy/create.py} +12 -14
  32. lightning_sdk/cli/{delete.py → legacy/delete.py} +5 -5
  33. lightning_sdk/cli/legacy/deploy/__init__.py +0 -0
  34. lightning_sdk/cli/{deploy → legacy/deploy}/_auth.py +5 -6
  35. lightning_sdk/cli/{deploy → legacy/deploy}/devbox.py +8 -2
  36. lightning_sdk/cli/{deploy → legacy/deploy}/serve.py +19 -8
  37. lightning_sdk/cli/{download.py → legacy/download.py} +14 -15
  38. lightning_sdk/cli/legacy/entrypoint.py +110 -0
  39. lightning_sdk/cli/{generate.py → legacy/generate.py} +1 -1
  40. lightning_sdk/cli/{inspection.py → legacy/inspection.py} +1 -1
  41. lightning_sdk/cli/{job_and_mmt_action.py → legacy/job_and_mmt_action.py} +6 -6
  42. lightning_sdk/cli/{jobs_menu.py → legacy/jobs_menu.py} +1 -1
  43. lightning_sdk/cli/{list.py → legacy/list.py} +12 -13
  44. lightning_sdk/cli/{mmts_menu.py → legacy/mmts_menu.py} +1 -1
  45. lightning_sdk/cli/{open.py → legacy/open.py} +4 -4
  46. lightning_sdk/cli/{start.py → legacy/start.py} +1 -0
  47. lightning_sdk/cli/{stop.py → legacy/stop.py} +1 -1
  48. lightning_sdk/cli/{switch.py → legacy/switch.py} +1 -0
  49. lightning_sdk/cli/{teamspace_menu.py → legacy/teamspace_menu.py} +1 -1
  50. lightning_sdk/cli/{upload.py → legacy/upload.py} +7 -8
  51. lightning_sdk/cli/license/__init__.py +14 -0
  52. lightning_sdk/cli/license/get.py +15 -0
  53. lightning_sdk/cli/license/list.py +45 -0
  54. lightning_sdk/cli/license/set.py +13 -0
  55. lightning_sdk/cli/mmt/__init__.py +7 -0
  56. lightning_sdk/cli/studio/__init__.py +24 -0
  57. lightning_sdk/cli/studio/connect.py +139 -0
  58. lightning_sdk/cli/studio/create.py +96 -0
  59. lightning_sdk/cli/studio/delete.py +49 -0
  60. lightning_sdk/cli/studio/list.py +85 -0
  61. lightning_sdk/cli/studio/ssh.py +64 -0
  62. lightning_sdk/cli/studio/start.py +115 -0
  63. lightning_sdk/cli/studio/stop.py +45 -0
  64. lightning_sdk/cli/studio/switch.py +66 -0
  65. lightning_sdk/cli/utils/__init__.py +7 -0
  66. lightning_sdk/cli/utils/cloud_account_map.py +10 -0
  67. lightning_sdk/cli/utils/get_base_studio.py +24 -0
  68. lightning_sdk/cli/utils/handle_machine_and_gpus_args.py +69 -0
  69. lightning_sdk/cli/utils/logging.py +122 -0
  70. lightning_sdk/cli/utils/owner_selection.py +110 -0
  71. lightning_sdk/cli/utils/resolve.py +28 -0
  72. lightning_sdk/cli/utils/richt_print.py +35 -0
  73. lightning_sdk/cli/utils/save_to_config.py +27 -0
  74. lightning_sdk/cli/utils/ssh_connection.py +59 -0
  75. lightning_sdk/cli/utils/studio_selection.py +113 -0
  76. lightning_sdk/cli/utils/teamspace_selection.py +125 -0
  77. lightning_sdk/cli/vm/__init__.py +20 -0
  78. lightning_sdk/cli/vm/create.py +33 -0
  79. lightning_sdk/cli/vm/delete.py +25 -0
  80. lightning_sdk/cli/vm/list.py +30 -0
  81. lightning_sdk/cli/vm/ssh.py +31 -0
  82. lightning_sdk/cli/vm/start.py +60 -0
  83. lightning_sdk/cli/vm/stop.py +25 -0
  84. lightning_sdk/cli/vm/switch.py +38 -0
  85. lightning_sdk/constants.py +1 -0
  86. lightning_sdk/deployment/__init__.py +2 -0
  87. lightning_sdk/deployment/deployment.py +17 -2
  88. lightning_sdk/helpers.py +56 -37
  89. lightning_sdk/job/base.py +21 -6
  90. lightning_sdk/job/job.py +13 -0
  91. lightning_sdk/job/v1.py +11 -0
  92. lightning_sdk/job/v2.py +12 -0
  93. lightning_sdk/lightning_cloud/login.py +320 -10
  94. lightning_sdk/lightning_cloud/openapi/__init__.py +113 -3
  95. lightning_sdk/lightning_cloud/openapi/api/__init__.py +3 -0
  96. lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +713 -75
  97. lightning_sdk/lightning_cloud/openapi/api/auth_service_api.py +376 -0
  98. lightning_sdk/lightning_cloud/openapi/api/billing_service_api.py +191 -1
  99. lightning_sdk/lightning_cloud/openapi/api/cloud_space_environment_template_service_api.py +5 -1
  100. lightning_sdk/lightning_cloud/openapi/api/cloud_space_service_api.py +420 -0
  101. lightning_sdk/lightning_cloud/openapi/api/cloudy_service_api.py +0 -97
  102. lightning_sdk/lightning_cloud/openapi/api/cluster_service_api.py +420 -0
  103. lightning_sdk/lightning_cloud/openapi/api/data_connection_service_api.py +101 -0
  104. lightning_sdk/lightning_cloud/openapi/api/incidents_service_api.py +1058 -0
  105. lightning_sdk/lightning_cloud/openapi/api/jobs_service_api.py +121 -0
  106. lightning_sdk/lightning_cloud/openapi/api/k8_s_cluster_service_api.py +1742 -94
  107. lightning_sdk/lightning_cloud/openapi/api/markets_service_api.py +145 -0
  108. lightning_sdk/lightning_cloud/openapi/api/models_store_api.py +4 -4
  109. lightning_sdk/lightning_cloud/openapi/api/product_license_service_api.py +108 -108
  110. lightning_sdk/lightning_cloud/openapi/api/projects_service_api.py +105 -0
  111. lightning_sdk/lightning_cloud/openapi/api/schedules_service_api.py +347 -0
  112. lightning_sdk/lightning_cloud/openapi/api/sdk_command_history_service_api.py +141 -0
  113. lightning_sdk/lightning_cloud/openapi/api/storage_service_api.py +761 -1
  114. lightning_sdk/lightning_cloud/openapi/configuration.py +3 -19
  115. lightning_sdk/lightning_cloud/openapi/models/__init__.py +110 -3
  116. lightning_sdk/lightning_cloud/openapi/models/assistant_id_conversations_body.py +15 -15
  117. lightning_sdk/lightning_cloud/openapi/models/cloudspace_id_visibility_body.py +27 -1
  118. lightning_sdk/lightning_cloud/openapi/models/cluster_id_kubernetestemplates_body.py +201 -0
  119. lightning_sdk/lightning_cloud/openapi/models/cluster_id_metrics_body.py +131 -1
  120. lightning_sdk/lightning_cloud/openapi/models/create.py +27 -1
  121. lightning_sdk/lightning_cloud/openapi/models/create_machine_request_represents_the_request_to_create_a_machine.py +461 -0
  122. lightning_sdk/lightning_cloud/openapi/models/deployments_id_body.py +27 -1
  123. lightning_sdk/lightning_cloud/openapi/models/externalv1_cloud_space_instance_status.py +105 -1
  124. lightning_sdk/lightning_cloud/openapi/models/externalv1_user_status.py +27 -1
  125. lightning_sdk/lightning_cloud/openapi/models/id_codeconfig_body.py +3 -81
  126. lightning_sdk/lightning_cloud/openapi/models/id_fork_body1.py +27 -1
  127. lightning_sdk/lightning_cloud/openapi/models/id_render_body.py +123 -0
  128. lightning_sdk/lightning_cloud/openapi/models/id_sleepconfig_body.py +175 -0
  129. lightning_sdk/lightning_cloud/openapi/models/id_transfer_body.py +53 -1
  130. lightning_sdk/lightning_cloud/openapi/models/incident_id_messages_body.py +123 -0
  131. lightning_sdk/lightning_cloud/openapi/models/incidents_id_body.py +279 -0
  132. lightning_sdk/lightning_cloud/openapi/models/job_id_reportroutingtelemetry_body.py +123 -0
  133. lightning_sdk/lightning_cloud/openapi/models/kubernetestemplates_id_body.py +201 -0
  134. lightning_sdk/lightning_cloud/openapi/models/license_key_validate_body.py +123 -0
  135. lightning_sdk/lightning_cloud/openapi/models/message_id_actions_body.py +201 -0
  136. lightning_sdk/lightning_cloud/openapi/models/messages_message_id_body.py +123 -0
  137. lightning_sdk/lightning_cloud/openapi/models/metricsstream_create_body.py +27 -1
  138. lightning_sdk/lightning_cloud/openapi/models/models_model_id_body.py +109 -31
  139. lightning_sdk/lightning_cloud/openapi/models/models_model_id_body1.py +149 -0
  140. lightning_sdk/lightning_cloud/openapi/models/orgs_id_body.py +53 -1
  141. lightning_sdk/lightning_cloud/openapi/models/project_id_storage_body.py +27 -1
  142. lightning_sdk/lightning_cloud/openapi/models/project_id_storagetransfers_body.py +175 -0
  143. lightning_sdk/lightning_cloud/openapi/models/project_tab_management_messages.py +123 -0
  144. lightning_sdk/lightning_cloud/openapi/models/projects_id_body.py +79 -1
  145. lightning_sdk/lightning_cloud/openapi/models/storage_complete_body.py +41 -15
  146. lightning_sdk/lightning_cloud/openapi/models/storagetransfers_validate_body.py +149 -0
  147. lightning_sdk/lightning_cloud/openapi/models/update1.py +27 -1
  148. lightning_sdk/lightning_cloud/openapi/models/uploads_upload_id_body1.py +27 -1
  149. lightning_sdk/lightning_cloud/openapi/models/user_id_affiliatelinks_body.py +107 -3
  150. lightning_sdk/lightning_cloud/openapi/models/v1_abort_storage_transfer_response.py +97 -0
  151. lightning_sdk/lightning_cloud/openapi/models/v1_aggregated_pod_metrics.py +799 -0
  152. lightning_sdk/lightning_cloud/openapi/models/v1_ai_pod_v1.py +53 -1
  153. lightning_sdk/lightning_cloud/openapi/models/v1_assistant_session_daily_aggregated.py +27 -1
  154. lightning_sdk/lightning_cloud/openapi/models/v1_billing_tier.py +0 -1
  155. lightning_sdk/lightning_cloud/openapi/models/v1_cancel_running_cloud_space_instance_transfer_response.py +97 -0
  156. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_provider.py +2 -0
  157. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_environment_template_config.py +27 -1
  158. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_specialized_view.py +1 -0
  159. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_transfer_metadata.py +147 -17
  160. lightning_sdk/lightning_cloud/openapi/models/v1_cloudflare_v1.py +3 -29
  161. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_accelerator.py +53 -1
  162. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_capacity_reservation.py +27 -1
  163. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_metrics.py +1527 -0
  164. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_security_options.py +27 -1
  165. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_spec.py +53 -1
  166. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_type.py +1 -0
  167. lightning_sdk/lightning_cloud/openapi/models/v1_container_metrics.py +21 -21
  168. lightning_sdk/lightning_cloud/openapi/models/v1_create_incident_request.py +305 -0
  169. lightning_sdk/lightning_cloud/openapi/models/v1_create_license_request.py +175 -0
  170. lightning_sdk/lightning_cloud/openapi/models/v1_create_machine_response.py +123 -0
  171. lightning_sdk/lightning_cloud/openapi/models/v1_create_model_metrics_response.py +97 -0
  172. lightning_sdk/lightning_cloud/openapi/models/v1_create_project_request.py +79 -1
  173. lightning_sdk/lightning_cloud/openapi/models/v1_create_sdk_command_history_request.py +253 -0
  174. lightning_sdk/lightning_cloud/openapi/models/v1_create_sdk_command_history_response.py +97 -0
  175. lightning_sdk/lightning_cloud/openapi/models/v1_daily_model_metrics.py +149 -0
  176. lightning_sdk/lightning_cloud/openapi/models/v1_data_connection.py +53 -1
  177. lightning_sdk/lightning_cloud/openapi/models/v1_delete_incident_message_response.py +97 -0
  178. lightning_sdk/lightning_cloud/openapi/models/v1_delete_incident_response.py +97 -0
  179. lightning_sdk/lightning_cloud/openapi/models/v1_delete_kubernetes_template_response.py +97 -0
  180. lightning_sdk/lightning_cloud/openapi/models/v1_delete_license_response.py +97 -0
  181. lightning_sdk/lightning_cloud/openapi/models/v1_delete_machine_response.py +97 -0
  182. lightning_sdk/lightning_cloud/openapi/models/v1_deployment.py +27 -1
  183. lightning_sdk/lightning_cloud/openapi/models/v1_external_cluster_spec.py +53 -1
  184. lightning_sdk/lightning_cloud/openapi/models/v1_external_search_user.py +27 -1
  185. lightning_sdk/lightning_cloud/openapi/models/v1_filestore_data_connection.py +27 -1
  186. lightning_sdk/lightning_cloud/openapi/models/v1_filesystem_metric.py +201 -0
  187. lightning_sdk/lightning_cloud/openapi/models/v1_firewall_rule.py +175 -0
  188. lightning_sdk/lightning_cloud/openapi/models/v1_get_cloud_space_required_balance_status_response.py +149 -0
  189. lightning_sdk/lightning_cloud/openapi/models/v1_get_cloud_space_transfer_estimate_response.py +149 -0
  190. lightning_sdk/lightning_cloud/openapi/models/v1_get_latest_model_metrics_response.py +123 -0
  191. lightning_sdk/lightning_cloud/openapi/models/v1_get_machine_response.py +123 -0
  192. lightning_sdk/lightning_cloud/openapi/models/v1_get_market_pricing_response.py +201 -0
  193. lightning_sdk/lightning_cloud/openapi/models/v1_get_model_metrics_response.py +123 -0
  194. lightning_sdk/lightning_cloud/openapi/models/v1_get_temp_bucket_credentials_response.py +201 -0
  195. lightning_sdk/lightning_cloud/openapi/models/v1_get_user_response.py +41 -15
  196. lightning_sdk/lightning_cloud/openapi/models/v1_google_cloud_direct_v1.py +27 -1
  197. lightning_sdk/lightning_cloud/openapi/models/v1_group_node_metrics.py +1215 -0
  198. lightning_sdk/lightning_cloud/openapi/models/v1_group_pod_metrics.py +1241 -0
  199. lightning_sdk/lightning_cloud/openapi/models/v1_guest_login_request.py +177 -0
  200. lightning_sdk/lightning_cloud/openapi/models/v1_guest_login_response.py +149 -0
  201. lightning_sdk/lightning_cloud/openapi/models/v1_guest_user.py +201 -0
  202. lightning_sdk/lightning_cloud/openapi/models/v1_incident.py +565 -0
  203. lightning_sdk/lightning_cloud/openapi/models/v1_incident_detail.py +149 -0
  204. lightning_sdk/lightning_cloud/openapi/models/v1_incident_event.py +591 -0
  205. lightning_sdk/lightning_cloud/openapi/models/v1_incident_message.py +253 -0
  206. lightning_sdk/lightning_cloud/openapi/models/v1_incident_severity.py +105 -0
  207. lightning_sdk/lightning_cloud/openapi/models/v1_incident_type.py +108 -0
  208. lightning_sdk/lightning_cloud/openapi/models/v1_job.py +53 -1
  209. lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +27 -1
  210. lightning_sdk/lightning_cloud/openapi/models/v1_k8s_incident_indexes.py +149 -0
  211. lightning_sdk/lightning_cloud/openapi/models/v1_kai_scheduler_queue_metrics.py +627 -0
  212. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_aws_config.py +279 -0
  213. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_settings_v1.py +253 -0
  214. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_v1.py +107 -3
  215. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_template.py +357 -0
  216. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_template_property.py +227 -0
  217. lightning_sdk/lightning_cloud/openapi/models/v1_lambda_labs_direct_v1.py +29 -3
  218. lightning_sdk/lightning_cloud/openapi/models/v1_license.py +227 -0
  219. lightning_sdk/lightning_cloud/openapi/models/v1_lightning_elastic_cluster_v1.py +97 -0
  220. lightning_sdk/lightning_cloud/openapi/models/v1_list_aggregated_pod_metrics_response.py +123 -0
  221. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_metric_timestamps_response.py +123 -0
  222. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_metrics_response.py +123 -0
  223. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_namespace_metrics_response.py +123 -0
  224. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_namespace_user_metrics_response.py +123 -0
  225. lightning_sdk/lightning_cloud/openapi/models/v1_list_conversation_message_actions_response.py +123 -0
  226. lightning_sdk/lightning_cloud/openapi/models/v1_list_filesystem_metrics_response.py +123 -0
  227. lightning_sdk/lightning_cloud/openapi/models/v1_list_group_pod_metrics_response.py +123 -0
  228. lightning_sdk/lightning_cloud/openapi/models/v1_list_incident_events_response.py +123 -0
  229. lightning_sdk/lightning_cloud/openapi/models/v1_list_incident_messages_response.py +149 -0
  230. lightning_sdk/lightning_cloud/openapi/models/v1_list_incidents_response.py +149 -0
  231. lightning_sdk/lightning_cloud/openapi/models/v1_list_kai_scheduler_queues_metrics_response.py +123 -0
  232. lightning_sdk/lightning_cloud/openapi/models/v1_list_kubernetes_templates_response.py +123 -0
  233. lightning_sdk/lightning_cloud/openapi/models/{v1_list_product_licenses_response.py → v1_list_license_response.py} +16 -16
  234. lightning_sdk/lightning_cloud/openapi/models/v1_list_machines_response.py +149 -0
  235. lightning_sdk/lightning_cloud/openapi/models/v1_list_platform_notifications_response.py +123 -0
  236. lightning_sdk/lightning_cloud/openapi/models/v1_list_schedule_runs_response.py +123 -0
  237. lightning_sdk/lightning_cloud/openapi/models/v1_list_storage_transfers_response.py +123 -0
  238. lightning_sdk/lightning_cloud/openapi/models/v1_lustre_data_connection.py +149 -0
  239. lightning_sdk/lightning_cloud/openapi/models/v1_machine.py +617 -0
  240. lightning_sdk/lightning_cloud/openapi/models/v1_machine_direct_v1.py +123 -0
  241. lightning_sdk/lightning_cloud/openapi/models/v1_magic_link_login_request.py +1 -27
  242. lightning_sdk/lightning_cloud/openapi/models/v1_magic_link_login_response.py +27 -1
  243. lightning_sdk/lightning_cloud/openapi/models/v1_managed_model.py +29 -3
  244. lightning_sdk/lightning_cloud/openapi/models/v1_market_price.py +149 -0
  245. lightning_sdk/lightning_cloud/openapi/models/v1_membership.py +53 -1
  246. lightning_sdk/lightning_cloud/openapi/models/v1_message_action.py +279 -0
  247. lightning_sdk/lightning_cloud/openapi/models/v1_metrics_stream.py +27 -1
  248. lightning_sdk/lightning_cloud/openapi/models/v1_model_metrics.py +175 -0
  249. lightning_sdk/lightning_cloud/openapi/models/v1_namespace_metrics.py +591 -0
  250. lightning_sdk/lightning_cloud/openapi/models/v1_namespace_user_metrics.py +435 -0
  251. lightning_sdk/lightning_cloud/openapi/models/v1_nebius_direct_v1.py +29 -3
  252. lightning_sdk/lightning_cloud/openapi/models/v1_node_metrics.py +361 -23
  253. lightning_sdk/lightning_cloud/openapi/models/v1_notification_type.py +1 -0
  254. lightning_sdk/lightning_cloud/openapi/models/v1_organization.py +53 -1
  255. lightning_sdk/lightning_cloud/openapi/models/v1_pause_storage_transfer_response.py +97 -0
  256. lightning_sdk/lightning_cloud/openapi/models/v1_platform_notification.py +279 -0
  257. lightning_sdk/lightning_cloud/openapi/models/v1_pod_metrics.py +335 -23
  258. lightning_sdk/lightning_cloud/openapi/models/v1_project.py +27 -1
  259. lightning_sdk/lightning_cloud/openapi/models/v1_project_cluster_binding.py +27 -1
  260. lightning_sdk/lightning_cloud/openapi/models/v1_project_membership.py +53 -1
  261. lightning_sdk/lightning_cloud/openapi/models/v1_project_settings.py +53 -1
  262. lightning_sdk/lightning_cloud/openapi/models/v1_project_tab.py +149 -0
  263. lightning_sdk/lightning_cloud/openapi/models/{v1_product_license_check_response.py → v1_purchase_annual_upsell_request.py} +23 -23
  264. lightning_sdk/lightning_cloud/openapi/models/v1_purchase_annual_upsell_response.py +123 -0
  265. lightning_sdk/lightning_cloud/openapi/models/v1_quote_annual_upsell_response.py +227 -0
  266. lightning_sdk/lightning_cloud/openapi/models/v1_render_kubernetes_template_response.py +123 -0
  267. lightning_sdk/lightning_cloud/openapi/models/v1_report_deployment_routing_telemetry_response.py +97 -0
  268. lightning_sdk/lightning_cloud/openapi/models/v1_required_balance_reason.py +107 -0
  269. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_request.py +97 -0
  270. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_response.py +123 -0
  271. lightning_sdk/lightning_cloud/openapi/models/v1_resource_visibility.py +1 -27
  272. lightning_sdk/lightning_cloud/openapi/models/v1_resume_storage_transfer_response.py +97 -0
  273. lightning_sdk/lightning_cloud/openapi/models/v1_routing_telemetry.py +79 -1
  274. lightning_sdk/lightning_cloud/openapi/models/v1_rule_resource.py +1 -0
  275. lightning_sdk/lightning_cloud/openapi/models/v1_schedule_run.py +357 -0
  276. lightning_sdk/lightning_cloud/openapi/models/v1_sdk_command_history_severity.py +104 -0
  277. lightning_sdk/lightning_cloud/openapi/models/v1_sdk_command_history_type.py +104 -0
  278. lightning_sdk/lightning_cloud/openapi/models/v1_secret_type.py +1 -0
  279. lightning_sdk/lightning_cloud/openapi/models/v1_server_alert_type.py +1 -0
  280. lightning_sdk/lightning_cloud/openapi/models/v1_slack_notifier.py +201 -0
  281. lightning_sdk/lightning_cloud/openapi/models/v1_slack_notifier_type.py +105 -0
  282. lightning_sdk/lightning_cloud/openapi/models/v1_storage_asset.py +133 -3
  283. lightning_sdk/lightning_cloud/openapi/models/v1_storage_transfer.py +435 -0
  284. lightning_sdk/lightning_cloud/openapi/models/v1_storage_transfer_status.py +108 -0
  285. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_request.py +123 -0
  286. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_response.py +123 -0
  287. lightning_sdk/lightning_cloud/openapi/models/v1_token_owner_type.py +104 -0
  288. lightning_sdk/lightning_cloud/openapi/models/v1_update_cloud_space_instance_config_request.py +3 -81
  289. lightning_sdk/lightning_cloud/openapi/models/v1_update_project_tab_order_response.py +123 -0
  290. lightning_sdk/lightning_cloud/openapi/models/v1_update_user_request.py +41 -15
  291. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +444 -600
  292. lightning_sdk/lightning_cloud/openapi/models/v1_validate_license_response.py +123 -0
  293. lightning_sdk/lightning_cloud/openapi/models/v1_validate_storage_transfer_response.py +123 -0
  294. lightning_sdk/lightning_cloud/openapi/models/v1_voltage_park_direct_v1.py +29 -3
  295. lightning_sdk/lightning_cloud/rest_client.py +48 -45
  296. lightning_sdk/lightning_cloud/utils/data_connection.py +51 -1
  297. lightning_sdk/llm/llm.py +175 -56
  298. lightning_sdk/llm/public_assistants.py +44 -7
  299. lightning_sdk/machine.py +21 -2
  300. lightning_sdk/mmt/base.py +7 -0
  301. lightning_sdk/mmt/mmt.py +11 -3
  302. lightning_sdk/mmt/v1.py +3 -1
  303. lightning_sdk/mmt/v2.py +4 -0
  304. lightning_sdk/owner.py +2 -1
  305. lightning_sdk/pipeline/steps.py +6 -0
  306. lightning_sdk/plugin.py +6 -1
  307. lightning_sdk/studio.py +294 -53
  308. lightning_sdk/teamspace.py +167 -7
  309. lightning_sdk/user.py +19 -1
  310. lightning_sdk/utils/config.py +179 -0
  311. lightning_sdk/utils/license.py +13 -0
  312. lightning_sdk/utils/logging.py +79 -0
  313. lightning_sdk/utils/names.py +1179 -0
  314. lightning_sdk/utils/progress.py +283 -0
  315. lightning_sdk/utils/resolve.py +82 -7
  316. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/METADATA +2 -1
  317. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/RECORD +328 -169
  318. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/entry_points.txt +1 -0
  319. lightning_sdk/lightning_cloud/openapi/models/v1_product_license.py +0 -435
  320. lightning_sdk/services/license.py +0 -363
  321. /lightning_sdk/cli/{deploy → legacy}/__init__.py +0 -0
  322. /lightning_sdk/cli/{ai_hub.py → legacy/ai_hub.py} +0 -0
  323. /lightning_sdk/cli/{docker_cli.py → legacy/docker_cli.py} +0 -0
  324. /lightning_sdk/cli/{exceptions.py → legacy/exceptions.py} +0 -0
  325. /lightning_sdk/cli/{run.py → legacy/run.py} +0 -0
  326. /lightning_sdk/cli/{studios_menu.py → legacy/studios_menu.py} +0 -0
  327. /lightning_sdk/cli/{coloring.py → utils/coloring.py} +0 -0
  328. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/LICENSE +0 -0
  329. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/WHEEL +0 -0
  330. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,20 @@
1
- from typing import List, Union
1
+ import re
2
+ from typing import Dict, List, Optional, Union
2
3
 
3
4
  from lightning_sdk.lightning_cloud.login import Auth
4
5
  from lightning_sdk.lightning_cloud.openapi import (
6
+ SecretsIdBody1,
5
7
  V1CloudSpace,
8
+ V1CreateUserSecretRequest,
6
9
  V1GetUserResponse,
7
10
  V1ListCloudSpacesResponse,
8
11
  V1Membership,
9
12
  V1Organization,
10
13
  V1SearchUser,
14
+ V1Secret,
11
15
  V1UserFeatures,
12
16
  )
17
+ from lightning_sdk.lightning_cloud.openapi.models.v1_secret_type import V1SecretType
13
18
  from lightning_sdk.lightning_cloud.rest_client import LightningClient
14
19
 
15
20
 
@@ -56,8 +61,14 @@ class UserApi:
56
61
  def _get_all_teamspace_memberships(
57
62
  self,
58
63
  user_id: str, # todo: this is unused, but still required
64
+ org_id: Optional[str] = None,
59
65
  ) -> List[V1Membership]:
60
- return self._client.projects_service_list_memberships(filter_by_user_id=True).memberships
66
+ kwargs: Dict[str, Union[bool, str]] = {"filter_by_user_id": True}
67
+
68
+ if org_id is not None:
69
+ kwargs["organization_id"] = org_id
70
+
71
+ return self._client.projects_service_list_memberships(**kwargs).memberships
61
72
 
62
73
  def _get_authed_user_name(self) -> str:
63
74
  """Gets the currently logged-in user."""
@@ -69,3 +80,46 @@ class UserApi:
69
80
  def _get_feature_flags(self) -> V1UserFeatures:
70
81
  resp: V1GetUserResponse = self._client.auth_service_get_user()
71
82
  return resp.features
83
+
84
+ def get_secrets(self) -> Dict[str, str]:
85
+ """Get all secrets for the current user."""
86
+ secrets = self._get_secrets()
87
+ # this returns encrypted values for security. It doesn't make sense to show them,
88
+ # so we just return a placeholder
89
+ # not a security issue to replace in the client as we get the encrypted values from the server.
90
+ return {secret.name: "***REDACTED***" for secret in secrets if secret.type == V1SecretType.UNSPECIFIED}
91
+
92
+ def set_secret(self, key: str, value: str) -> None:
93
+ """Set a secret for the current user.
94
+
95
+ This will replace the existing secret if it exists and create a new one if it doesn't.
96
+ """
97
+ secrets = self._get_secrets()
98
+ for secret in secrets:
99
+ if secret.name == key:
100
+ return self._update_secret(secret.id, value)
101
+ return self._create_secret(key, value)
102
+
103
+ def _get_secrets(self) -> List[V1Secret]:
104
+ return self._client.secret_service_list_user_secrets().secrets
105
+
106
+ def _update_secret(self, secret_id: str, value: str) -> None:
107
+ self._client.secret_service_update_user_secret(
108
+ body=SecretsIdBody1(value=value),
109
+ id=secret_id,
110
+ )
111
+
112
+ def _create_secret(
113
+ self,
114
+ key: str,
115
+ value: str,
116
+ ) -> None:
117
+ self._client.secret_service_create_user_secret(body=V1CreateUserSecretRequest(name=key, value=value))
118
+
119
+ def verify_secret_name(self, name: str) -> bool:
120
+ """Verify if a secret name is valid.
121
+
122
+ A valid secret name starts with a letter or underscore, followed by letters, digits, or underscores.
123
+ """
124
+ pattern = r"^[A-Za-z_][A-Za-z0-9_]*$"
125
+ return re.match(pattern, name) is not None
@@ -6,7 +6,7 @@ import re
6
6
  from concurrent.futures import ThreadPoolExecutor
7
7
  from functools import partial
8
8
  from pathlib import Path
9
- from typing import Any, Dict, List, Optional, Tuple, Union
9
+ from typing import Any, Callable, Dict, List, Optional, Tuple, TypedDict, Union
10
10
 
11
11
  import backoff
12
12
  import requests
@@ -19,6 +19,7 @@ from lightning_sdk.lightning_cloud.openapi import (
19
19
  ModelsStoreApi,
20
20
  ProjectIdStorageBody,
21
21
  StorageCompleteBody,
22
+ StorageServiceApi,
22
23
  UploadIdCompleteBody,
23
24
  UploadIdPartsBody,
24
25
  V1CompletedPart,
@@ -367,38 +368,40 @@ _DOWNLOAD_REQUEST_CHUNK_SIZE = 10 * _BYTES_PER_MB
367
368
  _DOWNLOAD_MIN_CHUNK_SIZE = 100 * _BYTES_PER_KB
368
369
 
369
370
 
371
+ class _RefreshResponse(TypedDict):
372
+ url: str
373
+ size: int
374
+
375
+
370
376
  class _FileDownloader:
371
377
  def __init__(
372
378
  self,
373
- client: LightningClient,
374
- model_id: str,
375
- version: str,
376
379
  teamspace_id: str,
377
380
  remote_path: str,
378
381
  file_path: str,
379
382
  executor: ThreadPoolExecutor,
380
383
  num_workers: int = 20,
381
384
  progress_bar: Optional[tqdm] = None,
385
+ url: Optional[str] = None,
386
+ size: Optional[int] = None,
387
+ refresh_fn: Optional[Callable[[], _RefreshResponse]] = None,
382
388
  ) -> None:
383
- self.api = ModelsStoreApi(client.api_client)
384
- self.model_id = model_id
385
- self.version = version
386
389
  self.teamspace_id = teamspace_id
387
390
  self.local_path = file_path
388
391
  self.remote_path = remote_path
389
392
  self.progress_bar = progress_bar
390
393
  self.num_workers = num_workers
391
- self._url = ""
392
- self._size = 0
394
+ self._url = url
395
+ self._size = size
393
396
  self.executor = executor
397
+ self.refresh_fn = refresh_fn
394
398
 
395
399
  @backoff.on_exception(backoff.expo, ApiException, max_tries=10)
396
400
  def refresh(self) -> None:
397
- response = self.api.models_store_get_model_file_url(
398
- project_id=self.teamspace_id, model_id=self.model_id, version=self.version, filepath=self.remote_path
399
- )
400
- self._url = response.url
401
- self._size = int(response.size)
401
+ if self.refresh_fn is not None:
402
+ response = self.refresh_fn()
403
+ self._url = response["url"]
404
+ self._size = response["size"]
402
405
 
403
406
  @property
404
407
  def url(self) -> str:
@@ -413,6 +416,11 @@ class _FileDownloader:
413
416
  return
414
417
  self.progress_bar.update(n)
415
418
 
419
+ def update_filename(self, desc: str) -> None:
420
+ if self.progress_bar is None:
421
+ return
422
+ self.progress_bar.set_description(f"{(desc[:72] + '...') if len(desc) > 75 else desc:<75.75}")
423
+
416
424
  @backoff.on_exception(backoff.expo, (requests.exceptions.HTTPError), max_tries=10)
417
425
  def _download_chunk(self, filename: str, start_end: Tuple[int]) -> None:
418
426
  start, end = start_end
@@ -447,6 +455,8 @@ class _FileDownloader:
447
455
  f.write(b"\x00" * remaining_size)
448
456
 
449
457
  def _multipart_download(self, filename: str, num_workers: int) -> None:
458
+ self.update_filename(f"Downloading {self.remote_path}")
459
+
450
460
  num_chunks = num_workers
451
461
  chunk_size = math.ceil(self.size / num_chunks)
452
462
 
@@ -464,7 +474,8 @@ class _FileDownloader:
464
474
  concurrent.futures.wait(futures)
465
475
 
466
476
  def download(self) -> None:
467
- self.refresh()
477
+ if self.url is None:
478
+ self.refresh()
468
479
 
469
480
  tmp_filename = f"{self.local_path}.download"
470
481
 
@@ -539,6 +550,15 @@ def _download_model_files(
539
550
  mininterval=1,
540
551
  )
541
552
 
553
+ def refresh_fn(filename: str) -> _RefreshResponse:
554
+ resp = api.models_store_get_model_file_url(
555
+ project_id=response.project_id,
556
+ model_id=response.model_id,
557
+ version=response.version,
558
+ filepath=filename,
559
+ )
560
+ return {"url": resp.url, "size": int(resp.size)}
561
+
542
562
  with ThreadPoolExecutor(max_workers=min(num_workers, len(response.filepaths))) as file_executor, ThreadPoolExecutor(
543
563
  max_workers=num_workers
544
564
  ) as part_executor:
@@ -549,15 +569,13 @@ def _download_model_files(
549
569
  local_file.parent.mkdir(parents=True, exist_ok=True)
550
570
 
551
571
  file_downloader = _FileDownloader(
552
- client=client,
553
- model_id=response.model_id,
554
- version=response.version,
555
572
  teamspace_id=response.project_id,
556
573
  remote_path=filepath,
557
574
  file_path=str(local_file),
558
575
  num_workers=num_workers,
559
576
  progress_bar=pbar,
560
577
  executor=part_executor,
578
+ refresh_fn=lambda f=filepath: refresh_fn(f),
561
579
  )
562
580
 
563
581
  futures.append(file_executor.submit(file_downloader.download))
@@ -568,6 +586,78 @@ def _download_model_files(
568
586
  return response.filepaths
569
587
 
570
588
 
589
+ def _download_teamspace_files(
590
+ client: LightningClient,
591
+ teamspace_id: str,
592
+ cluster_id: str,
593
+ prefix: str,
594
+ download_dir: Path,
595
+ progress_bar: bool,
596
+ num_workers: int = os.cpu_count() * 4,
597
+ ) -> None:
598
+ api = StorageServiceApi(client.api_client)
599
+ response = None
600
+
601
+ pbar = None
602
+ if progress_bar:
603
+ pbar = tqdm(
604
+ desc="Downloading files",
605
+ unit="B",
606
+ unit_scale=True,
607
+ unit_divisor=1000,
608
+ position=-1,
609
+ mininterval=1,
610
+ )
611
+
612
+ def refresh_fn(filename: str) -> _RefreshResponse:
613
+ resp = api.storage_service_list_project_artifacts(
614
+ project_id=teamspace_id,
615
+ cluster_id=cluster_id,
616
+ page_token="",
617
+ include_download_url=True,
618
+ prefix=prefix + filename,
619
+ page_size=1,
620
+ )
621
+ return {"url": resp.artifacts[0].url, "size": int(resp.artifacts[0].size_bytes)}
622
+
623
+ with ThreadPoolExecutor(max_workers=num_workers) as file_executor, ThreadPoolExecutor(
624
+ max_workers=num_workers
625
+ ) as part_executor:
626
+ while response is None or (response is not None and response.next_page_token != ""):
627
+ response = api.storage_service_list_project_artifacts(
628
+ project_id=teamspace_id,
629
+ cluster_id=cluster_id,
630
+ page_token=response.next_page_token if response is not None else "",
631
+ include_download_url=True,
632
+ prefix=prefix,
633
+ page_size=1000,
634
+ )
635
+
636
+ page_futures = []
637
+ for file in response.artifacts:
638
+ local_file = download_dir / file.filename
639
+ local_file.parent.mkdir(parents=True, exist_ok=True)
640
+
641
+ file_downloader = _FileDownloader(
642
+ teamspace_id=teamspace_id,
643
+ remote_path=file.filename,
644
+ file_path=str(local_file),
645
+ num_workers=num_workers,
646
+ progress_bar=pbar,
647
+ executor=part_executor,
648
+ url=file.url,
649
+ size=int(file.size_bytes),
650
+ refresh_fn=lambda f=file: refresh_fn(f.filename),
651
+ )
652
+
653
+ page_futures.append(file_executor.submit(file_downloader.download))
654
+
655
+ if page_futures:
656
+ concurrent.futures.wait(page_futures)
657
+
658
+ pbar.set_description("Download complete")
659
+
660
+
571
661
  def _create_app(
572
662
  client: CloudSpaceServiceApi,
573
663
  studio_id: str,
@@ -3,11 +3,11 @@ from typing import List, Optional, Union
3
3
 
4
4
  from lightning_sdk.api.base_studio_api import BaseStudioApi
5
5
  from lightning_sdk.api.user_api import UserApi
6
- from lightning_sdk.lightning_cloud import login
7
6
  from lightning_sdk.lightning_cloud.openapi.models.v1_cloud_space_environment_type import V1CloudSpaceEnvironmentType
8
7
  from lightning_sdk.organization import Organization
8
+ from lightning_sdk.teamspace import Teamspace
9
9
  from lightning_sdk.user import User
10
- from lightning_sdk.utils.resolve import _resolve_org, _resolve_user
10
+ from lightning_sdk.utils.resolve import _resolve_teamspace
11
11
 
12
12
 
13
13
  @dataclass
@@ -16,12 +16,15 @@ class BaseStudioInfo:
16
16
  name: str
17
17
  managed_id: str
18
18
  description: str
19
+ creator: str
20
+ enabled: bool
19
21
 
20
22
 
21
23
  class BaseStudio:
22
24
  def __init__(
23
25
  self,
24
26
  name: Optional[str] = None,
27
+ teamspace: Optional[Union[str, Teamspace]] = None,
25
28
  org: Optional[Union[str, Organization]] = None,
26
29
  user: Optional[Union[str, User]] = None,
27
30
  ) -> None:
@@ -36,26 +39,35 @@ class BaseStudio:
36
39
  Raises:
37
40
  ConnectionError: If there is an issue with the authentication process.
38
41
  """
39
- self._auth = login.Auth()
40
- self._user = None
42
+ self._teamspace = None
41
43
 
42
- try:
43
- self._auth.authenticate()
44
- if user is None:
45
- self._user = User(name=UserApi()._get_user_by_id(self._auth.user_id).username)
46
- except ConnectionError as e:
47
- raise e
44
+ _teamspace = _resolve_teamspace(teamspace=teamspace, org=org, user=user)
45
+ if _teamspace is None:
46
+ raise ValueError("Couldn't resolve teamspace from the provided name, org, or user")
48
47
 
49
- self._user = _resolve_user(self._user or user)
50
- self._org = _resolve_org(org)
48
+ self._teamspace = _teamspace
49
+
50
+ # self._auth = login.Auth()
51
+ # self._user = None
52
+
53
+ # try:
54
+ # self._auth.authenticate()
55
+ # if user is None:
56
+ # self._user = User(name=UserApi()._get_user_by_id(self._auth.user_id).username)
57
+ # except ConnectionError as e:
58
+ # raise e
59
+
60
+ # self._user = _resolve_user(self._user or user)
61
+ # self._org = _resolve_org(org)
51
62
 
52
63
  self._base_studio_api = BaseStudioApi()
53
64
 
54
65
  if name is not None:
55
- base_studio = self._base_studio_api.get_base_studio(name, self._org.id)
66
+ org_id = self._teamspace._org.id if self._teamspace._org is not None else None
67
+ base_studio = self._base_studio_api.get_base_studio(name, org_id)
56
68
 
57
69
  if base_studio is None:
58
- raise ValueError(f"Base studio with name {name} does not exist in organization {self._org.name}")
70
+ raise ValueError(f"Base studio with name {name} does not exist")
59
71
  self._base_studio = base_studio
60
72
 
61
73
  def update(
@@ -68,9 +80,11 @@ class BaseStudio:
68
80
  machine_image_version: Optional[str] = None,
69
81
  setup_script_text: Optional[str] = None,
70
82
  ) -> None:
83
+ org_id = self._teamspace._org.id if self._teamspace._org is not None else None
84
+ # TODO: if not in an org, can't update them
71
85
  self._base_studio = self._base_studio_api.update_base_studio(
72
86
  self._base_studio.id,
73
- self._org.id,
87
+ org_id,
74
88
  name=name,
75
89
  allowed_machines=allowed_machines,
76
90
  default_machine=default_machine,
@@ -80,20 +94,30 @@ class BaseStudio:
80
94
  disabled=disabled,
81
95
  )
82
96
 
83
- def list(self, managed: bool = True) -> List[BaseStudioInfo]:
97
+ def list(self, include_disabled: bool = False) -> List[BaseStudioInfo]:
84
98
  """List all base studios in the organization.
85
99
 
100
+ Args:
101
+ managed: Whether to filter for managed base studios.
102
+ include_disabled: Whether to include disabled base studios in the results.
103
+
86
104
  Returns:
87
- List[V1CloudSpaceEnvironmentTemplate]: A list of base studio templates.
105
+ List[BaseStudioInfo]: A list of base studio templates.
88
106
  """
89
- result = []
90
- for template in self._base_studio_api.get_all_base_studios(self._org.id, managed).templates:
91
- result.append(
92
- BaseStudioInfo(
93
- id=template.id,
94
- name=template.name,
95
- managed_id=template.managed_id,
96
- description=template.description,
97
- ),
107
+ org_id = self._teamspace._org.id if self._teamspace._org is not None else None
108
+ templates = self._base_studio_api.get_all_base_studios(org_id).templates
109
+
110
+ return [
111
+ BaseStudioInfo(
112
+ id=template.id,
113
+ name=template.name,
114
+ managed_id=template.managed_id,
115
+ description=template.description,
116
+ creator="⚡ Lightning AI"
117
+ if template.managed_id
118
+ else UserApi()._get_user_by_id(template.user_id).username,
119
+ enabled=not template.disabled,
98
120
  )
99
- return result
121
+ for template in templates
122
+ if include_disabled or not template.disabled
123
+ ]
@@ -0,0 +1 @@
1
+ """Lightning SDK CLI module."""
@@ -0,0 +1,10 @@
1
+ """Base Studio CLI commands."""
2
+
3
+ import click
4
+
5
+
6
+ def register_commands(group: click.Group) -> None:
7
+ """Register base studio commands with the given group."""
8
+ from lightning_sdk.cli.base_studio.list import list_base_studios
9
+
10
+ group.add_command(list_base_studios)
@@ -0,0 +1,43 @@
1
+ """Base Studio list command."""
2
+
3
+ import click
4
+ from rich.table import Table
5
+
6
+ from lightning_sdk.base_studio import BaseStudio
7
+ from lightning_sdk.cli.utils.richt_print import rich_to_str
8
+
9
+
10
+ @click.command("list")
11
+ @click.option("--include-disabled", help="Include disabled Base Studios in the list.", is_flag=True)
12
+ def list_base_studios(include_disabled: bool) -> None:
13
+ """List Base Studios in an org.
14
+
15
+ Example:
16
+ lightning base-studio list
17
+
18
+ """
19
+ return list_impl(include_disabled=include_disabled)
20
+
21
+
22
+ def list_impl(include_disabled: bool) -> None:
23
+ base_studio_cls = BaseStudio()
24
+ base_studios = base_studio_cls.list(include_disabled=include_disabled)
25
+
26
+ table = Table(
27
+ pad_edge=True,
28
+ )
29
+
30
+ table.add_column("Name")
31
+ table.add_column("Description")
32
+ table.add_column("Creator")
33
+ table.add_column("Enabled")
34
+
35
+ for base_studio in base_studios:
36
+ table.add_row(
37
+ base_studio.name.lower().replace(" ", "-"),
38
+ base_studio.description or "",
39
+ base_studio.creator,
40
+ "Yes" if base_studio.enabled else "No",
41
+ )
42
+
43
+ click.echo(rich_to_str(table), color=True)
@@ -0,0 +1,14 @@
1
+ """Config CLI commands."""
2
+
3
+ import click
4
+
5
+
6
+ def register_commands(group: click.Group) -> None:
7
+ """Register config commands with the given group."""
8
+ from lightning_sdk.cli.config.get import get
9
+ from lightning_sdk.cli.config.set import set_value
10
+ from lightning_sdk.cli.config.show import show
11
+
12
+ group.add_command(get)
13
+ group.add_command(set_value)
14
+ group.add_command(show)
@@ -0,0 +1,57 @@
1
+ import click
2
+
3
+ from lightning_sdk.utils.config import Config, DefaultConfigKeys
4
+
5
+
6
+ @click.group("get")
7
+ def get() -> None:
8
+ """Get configuration values."""
9
+
10
+
11
+ @get.command("user")
12
+ def get_user() -> None:
13
+ """Get the default user name from the config."""
14
+ config = Config()
15
+ user = config.get_value(DefaultConfigKeys.user)
16
+ click.echo(user)
17
+
18
+
19
+ @get.command("org")
20
+ def get_org() -> None:
21
+ """Get the default organization name from the config."""
22
+ config = Config()
23
+ org = config.get_value(DefaultConfigKeys.organization)
24
+ click.echo(org)
25
+
26
+
27
+ @get.command("teamspace")
28
+ def get_teamspace() -> None:
29
+ """Get the default teamspace name from the config."""
30
+ config = Config()
31
+ teamspace_name = config.get_value(DefaultConfigKeys.teamspace_name)
32
+ teamspace_owner = config.get_value(DefaultConfigKeys.teamspace_owner)
33
+ click.echo(f"{teamspace_owner}/{teamspace_name}")
34
+
35
+
36
+ @get.command("studio")
37
+ def get_studio() -> None:
38
+ """Get the default sutdio name from the config."""
39
+ config = Config()
40
+ studio = config.get_value(DefaultConfigKeys.studio)
41
+ click.echo(studio)
42
+
43
+
44
+ @get.command("cloud-account")
45
+ def get_cloud_account() -> None:
46
+ """Get the default cloud account name from the config."""
47
+ config = Config()
48
+ cloud_account = config.get_value(DefaultConfigKeys.cloud_account)
49
+ click.echo(cloud_account)
50
+
51
+
52
+ @get.command("cloud-provider")
53
+ def get_cloud_provider() -> None:
54
+ """Get the default cloud provider name from the config."""
55
+ config = Config()
56
+ cloud_provider = config.get_value(DefaultConfigKeys.cloud_provider)
57
+ click.echo(cloud_provider)
@@ -0,0 +1,92 @@
1
+ import click
2
+
3
+ from lightning_sdk.cli.utils.save_to_config import save_teamspace_to_config
4
+ from lightning_sdk.cli.utils.teamspace_selection import TeamspacesMenu
5
+ from lightning_sdk.machine import CloudProvider
6
+ from lightning_sdk.studio import Studio
7
+ from lightning_sdk.utils.config import Config, DefaultConfigKeys
8
+ from lightning_sdk.utils.resolve import _resolve_org, _resolve_user
9
+
10
+
11
+ @click.group("set")
12
+ def set_value() -> None:
13
+ """Set configuration values."""
14
+
15
+
16
+ @set_value.command("user")
17
+ @click.argument("user_name")
18
+ def set_user(user_name: str) -> None:
19
+ """Set the default user name in the config."""
20
+ try:
21
+ _resolve_user(user_name)
22
+ except Exception:
23
+ # TODO: make this a generic CLI error
24
+ raise ValueError(f"Could not resolve user: '{user_name}'. Does the user exist?") from None
25
+
26
+ config = Config()
27
+ setattr(config, DefaultConfigKeys.user, user_name)
28
+
29
+
30
+ @set_value.command("org")
31
+ @click.argument("org_name")
32
+ def set_org(org_name: str) -> None:
33
+ """Set the default organization name in the config."""
34
+ try:
35
+ _resolve_org(org_name)
36
+ except Exception:
37
+ # TODO: make this a generic CLI error
38
+ raise ValueError(f"Could not resolve organization: '{org_name}'. Does the organization exist?") from None
39
+
40
+ config = Config()
41
+ setattr(config, DefaultConfigKeys.organization, org_name)
42
+
43
+
44
+ @set_value.command("studio")
45
+ @click.argument("studio_name")
46
+ def set_studio(studio_name: str) -> None:
47
+ """Set the default studio name in the config."""
48
+ try:
49
+ studio = Studio(studio_name)
50
+ except Exception:
51
+ # TODO: make this a generic CLI error
52
+ raise ValueError(f"Could not resolve studio: '{studio_name}'. Does the studio exist?") from None
53
+
54
+ config = Config()
55
+ setattr(config, DefaultConfigKeys.studio, studio.name)
56
+
57
+
58
+ @set_value.command("teamspace")
59
+ @click.argument("teamspace_name")
60
+ def set_teamspace(teamspace_name: str) -> None:
61
+ """Set the default teamspace name in the config."""
62
+ menu = TeamspacesMenu()
63
+ teamspace_resolved = menu(teamspace=teamspace_name)
64
+
65
+ # explicit user action, so overwrite the config
66
+ save_teamspace_to_config(teamspace_resolved, overwrite=True)
67
+
68
+
69
+ @set_value.command("cloud-account")
70
+ @click.argument("cloud_account_name")
71
+ def set_cloud_account(cloud_account_name: str) -> None:
72
+ """Set the default cloud account name in the config."""
73
+ config = Config()
74
+ setattr(config, DefaultConfigKeys.cloud_account, cloud_account_name)
75
+
76
+
77
+ @set_value.command("cloud-provider")
78
+ @click.argument("cloud_provider_name")
79
+ def set_cloud_provider(cloud_provider_name: str) -> None:
80
+ """Set the default cloud provider name in the config."""
81
+ config = Config()
82
+
83
+ try:
84
+ cloud_provider = CloudProvider(cloud_provider_name)
85
+ except ValueError:
86
+ # TODO: make this a generic CLI error
87
+ raise ValueError(
88
+ f"Could not resolve cloud provider: '{cloud_provider_name}'. "
89
+ f"Supported values are: {', '.join(m.name for m in list(CloudProvider))}"
90
+ ) from None
91
+
92
+ setattr(config, DefaultConfigKeys.cloud_provider, cloud_provider.name)
@@ -0,0 +1,9 @@
1
+ import click
2
+
3
+ from lightning_sdk.utils.config import Config
4
+
5
+
6
+ @click.command("show")
7
+ def show() -> None:
8
+ """Show configuration values."""
9
+ click.echo(Config())