hud-python 0.5.36__tar.gz → 0.5.37__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 (357) hide show
  1. {hud_python-0.5.36 → hud_python-0.5.37}/PKG-INFO +1 -1
  2. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/__init__.py +2 -0
  3. hud_python-0.5.37/hud/cli/login.py +293 -0
  4. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_build.py +2 -2
  5. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_sync.py +0 -1
  6. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/api.py +2 -1
  7. {hud_python-0.5.36 → hud_python-0.5.37}/hud/settings.py +6 -0
  8. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/test_version.py +1 -1
  9. {hud_python-0.5.36 → hud_python-0.5.37}/hud/version.py +1 -1
  10. {hud_python-0.5.36 → hud_python-0.5.37}/pyproject.toml +1 -1
  11. {hud_python-0.5.36 → hud_python-0.5.37}/.gitignore +0 -0
  12. {hud_python-0.5.36 → hud_python-0.5.37}/LICENSE +0 -0
  13. {hud_python-0.5.36 → hud_python-0.5.37}/README.md +0 -0
  14. {hud_python-0.5.36 → hud_python-0.5.37}/examples/README.md +0 -0
  15. {hud_python-0.5.36 → hud_python-0.5.37}/hud/__init__.py +0 -0
  16. {hud_python-0.5.36 → hud_python-0.5.37}/hud/__main__.py +0 -0
  17. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/__init__.py +0 -0
  18. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/base.py +0 -0
  19. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/claude.py +0 -0
  20. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/gateway.py +0 -0
  21. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/gemini.py +0 -0
  22. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/gemini_cua.py +0 -0
  23. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/grounded_openai.py +0 -0
  24. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/misc/__init__.py +0 -0
  25. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/misc/integration_test_agent.py +0 -0
  26. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/misc/response_agent.py +0 -0
  27. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/openai.py +0 -0
  28. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/openai_chat.py +0 -0
  29. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/operator.py +0 -0
  30. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/resolver.py +0 -0
  31. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/__init__.py +0 -0
  32. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/conftest.py +0 -0
  33. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_base.py +0 -0
  34. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_base_runtime.py +0 -0
  35. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_claude.py +0 -0
  36. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_gemini.py +0 -0
  37. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_grounded_openai_agent.py +0 -0
  38. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_integration_test_agent.py +0 -0
  39. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_openai.py +0 -0
  40. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_operator.py +0 -0
  41. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_resolver.py +0 -0
  42. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/tests/test_run_eval.py +0 -0
  43. {hud_python-0.5.36 → hud_python-0.5.37}/hud/agents/types.py +0 -0
  44. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/__main__.py +0 -0
  45. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/analyze.py +0 -0
  46. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/build.py +0 -0
  47. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/cancel.py +0 -0
  48. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/__init__.py +0 -0
  49. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/base.py +0 -0
  50. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/harbor.py +0 -0
  51. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/tests/__init__.py +0 -0
  52. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/tests/conftest.py +0 -0
  53. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/convert/tests/test_harbor.py +0 -0
  54. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/debug.py +0 -0
  55. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/deploy.py +0 -0
  56. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/dev.py +0 -0
  57. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/eval.py +0 -0
  58. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/__init__.py +0 -0
  59. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/dev.py +0 -0
  60. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/init.py +0 -0
  61. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/tasks.py +0 -0
  62. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/templates.py +0 -0
  63. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/tests/__init__.py +0 -0
  64. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/flows/tests/test_dev.py +0 -0
  65. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/init.py +0 -0
  66. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/link.py +0 -0
  67. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/models.py +0 -0
  68. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/push.py +0 -0
  69. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/rl.py +0 -0
  70. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/scenario.py +0 -0
  71. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/sync.py +0 -0
  72. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/__init__.py +0 -0
  73. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_analysis_utils.py +0 -0
  74. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_analyze.py +0 -0
  75. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_analyze_metadata.py +0 -0
  76. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_analyze_module.py +0 -0
  77. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_build_failure.py +0 -0
  78. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_build_module.py +0 -0
  79. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_cli_init.py +0 -0
  80. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_cli_main.py +0 -0
  81. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_cli_more_wrappers.py +0 -0
  82. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_cli_root.py +0 -0
  83. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_convert.py +0 -0
  84. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_debug.py +0 -0
  85. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_debug_directory_mode.py +0 -0
  86. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_deploy.py +0 -0
  87. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_dev.py +0 -0
  88. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_eval.py +0 -0
  89. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_eval_bedrock.py +0 -0
  90. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_init.py +0 -0
  91. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_lockfile_utils.py +0 -0
  92. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_main_module.py +0 -0
  93. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_mcp_server.py +0 -0
  94. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_push.py +0 -0
  95. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_push_happy.py +0 -0
  96. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_push_wrapper.py +0 -0
  97. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_rl.py +0 -0
  98. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_scenario.py +0 -0
  99. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/tests/test_utils.py +0 -0
  100. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/__init__.py +0 -0
  101. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/analysis.py +0 -0
  102. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/args.py +0 -0
  103. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/build_display.py +0 -0
  104. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/build_logs.py +0 -0
  105. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/collect.py +0 -0
  106. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/config.py +0 -0
  107. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/context.py +0 -0
  108. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/docker.py +0 -0
  109. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/env_check.py +0 -0
  110. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/environment.py +0 -0
  111. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/git.py +0 -0
  112. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/interactive.py +0 -0
  113. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/lockfile.py +0 -0
  114. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/logging.py +0 -0
  115. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/metadata.py +0 -0
  116. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/name_check.py +0 -0
  117. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/project_config.py +0 -0
  118. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/server.py +0 -0
  119. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/source_hash.py +0 -0
  120. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tasks.py +0 -0
  121. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/taskset.py +0 -0
  122. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/__init__.py +0 -0
  123. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_collect.py +0 -0
  124. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_config.py +0 -0
  125. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_docker.py +0 -0
  126. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_docker_hints.py +0 -0
  127. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_env_check.py +0 -0
  128. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_environment.py +0 -0
  129. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_git.py +0 -0
  130. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_interactive_module.py +0 -0
  131. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_logging_utils.py +0 -0
  132. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_metadata.py +0 -0
  133. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_source_hash.py +0 -0
  134. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/tests/test_tasks.py +0 -0
  135. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/validation.py +0 -0
  136. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/version_check.py +0 -0
  137. {hud_python-0.5.36 → hud_python-0.5.37}/hud/cli/utils/viewer.py +0 -0
  138. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/__init__.py +0 -0
  139. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/loader.py +0 -0
  140. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/runner.py +0 -0
  141. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/tests/__init__.py +0 -0
  142. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/tests/test_loader.py +0 -0
  143. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/tests/test_utils.py +0 -0
  144. {hud_python-0.5.36 → hud_python-0.5.37}/hud/datasets/utils.py +0 -0
  145. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/__init__.py +0 -0
  146. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connection.py +0 -0
  147. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/__init__.py +0 -0
  148. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/base.py +0 -0
  149. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/local.py +0 -0
  150. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/mcp_config.py +0 -0
  151. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/openai.py +0 -0
  152. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/connectors/remote.py +0 -0
  153. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/environment.py +0 -0
  154. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/__init__.py +0 -0
  155. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/adk.py +0 -0
  156. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/anthropic.py +0 -0
  157. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/gemini.py +0 -0
  158. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/langchain.py +0 -0
  159. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/llamaindex.py +0 -0
  160. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/integrations/openai.py +0 -0
  161. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/mock.py +0 -0
  162. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/router.py +0 -0
  163. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/scenarios.py +0 -0
  164. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/__init__.py +0 -0
  165. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_connection.py +0 -0
  166. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_connectors.py +0 -0
  167. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_environment.py +0 -0
  168. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_integrations.py +0 -0
  169. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_local_connectors.py +0 -0
  170. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_scenarios.py +0 -0
  171. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_session_id.py +0 -0
  172. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/tests/test_tools.py +0 -0
  173. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/types.py +0 -0
  174. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/utils/__init__.py +0 -0
  175. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/utils/formats.py +0 -0
  176. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/utils/schema.py +0 -0
  177. {hud_python-0.5.36 → hud_python-0.5.37}/hud/environment/utils/tool_wrappers.py +0 -0
  178. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/__init__.py +0 -0
  179. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/context.py +0 -0
  180. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/display.py +0 -0
  181. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/instrument.py +0 -0
  182. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/manager.py +0 -0
  183. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/parallel.py +0 -0
  184. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/task.py +0 -0
  185. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/__init__.py +0 -0
  186. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/test_context.py +0 -0
  187. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/test_eval.py +0 -0
  188. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/test_manager.py +0 -0
  189. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/test_parallel.py +0 -0
  190. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/tests/test_task.py +0 -0
  191. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/types.py +0 -0
  192. {hud_python-0.5.36 → hud_python-0.5.37}/hud/eval/utils.py +0 -0
  193. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/__init__.py +0 -0
  194. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/chat.py +0 -0
  195. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/graders.py +0 -0
  196. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/permissions.py +0 -0
  197. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/skills.py +0 -0
  198. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/tests/__init__.py +0 -0
  199. {hud_python-0.5.36 → hud_python-0.5.37}/hud/native/tests/test_graders.py +0 -0
  200. {hud_python-0.5.36 → hud_python-0.5.37}/hud/patches/__init__.py +0 -0
  201. {hud_python-0.5.36 → hud_python-0.5.37}/hud/patches/mcp_patches.py +0 -0
  202. {hud_python-0.5.36 → hud_python-0.5.37}/hud/patches/warnings.py +0 -0
  203. {hud_python-0.5.36 → hud_python-0.5.37}/hud/py.typed +0 -0
  204. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/__init__.py +0 -0
  205. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/context.py +0 -0
  206. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/helper/__init__.py +0 -0
  207. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/low_level.py +0 -0
  208. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/router.py +0 -0
  209. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/server.py +0 -0
  210. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/__init__.py +0 -0
  211. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_add_tool.py +0 -0
  212. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_context.py +0 -0
  213. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_mcp_server_handlers.py +0 -0
  214. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_mcp_server_integration.py +0 -0
  215. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_mcp_server_more.py +0 -0
  216. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_prefix_naming.py +0 -0
  217. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_run_wrapper.py +0 -0
  218. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_server_extra.py +0 -0
  219. {hud_python-0.5.36 → hud_python-0.5.37}/hud/server/tests/test_sigterm_runner.py +0 -0
  220. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/__init__.py +0 -0
  221. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/chat.py +0 -0
  222. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/chat_service.py +0 -0
  223. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/reply_metadata.py +0 -0
  224. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/tests/__init__.py +0 -0
  225. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/tests/test_chat.py +0 -0
  226. {hud_python-0.5.36 → hud_python-0.5.37}/hud/services/tests/test_chat_service.py +0 -0
  227. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/__init__.py +0 -0
  228. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/exceptions.py +0 -0
  229. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/hints.py +0 -0
  230. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/requests.py +0 -0
  231. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/tests/__init__.py +0 -0
  232. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/tests/test_exceptions.py +0 -0
  233. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/tests/test_hints.py +0 -0
  234. {hud_python-0.5.36 → hud_python-0.5.37}/hud/shared/tests/test_requests.py +0 -0
  235. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/__init__.py +0 -0
  236. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/exporter.py +0 -0
  237. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/instrument.py +0 -0
  238. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/tests/__init__.py +0 -0
  239. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/tests/test_eval_telemetry.py +0 -0
  240. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/tests/test_exporter.py +0 -0
  241. {hud_python-0.5.36 → hud_python-0.5.37}/hud/telemetry/tests/test_instrument.py +0 -0
  242. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/__init__.py +0 -0
  243. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/agent.py +0 -0
  244. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/base.py +0 -0
  245. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/__init__.py +0 -0
  246. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/apply_patch.py +0 -0
  247. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/bash.py +0 -0
  248. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/edit.py +0 -0
  249. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/gemini_edit.py +0 -0
  250. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/gemini_shell.py +0 -0
  251. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/gemini_write.py +0 -0
  252. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/session.py +0 -0
  253. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/shell.py +0 -0
  254. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/__init__.py +0 -0
  255. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_apply_patch.py +0 -0
  256. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_bash.py +0 -0
  257. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_bash_extended.py +0 -0
  258. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_bash_integration.py +0 -0
  259. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_edit.py +0 -0
  260. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_gemini_tools.py +0 -0
  261. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/tests/test_shell.py +0 -0
  262. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/coding/utils.py +0 -0
  263. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/__init__.py +0 -0
  264. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/anthropic.py +0 -0
  265. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/gemini.py +0 -0
  266. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/glm.py +0 -0
  267. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/hud.py +0 -0
  268. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/openai.py +0 -0
  269. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/qwen.py +0 -0
  270. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/settings.py +0 -0
  271. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/tests/__init__.py +0 -0
  272. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/tests/test_compression.py +0 -0
  273. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/tests/test_computer.py +0 -0
  274. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/tests/test_computer_actions.py +0 -0
  275. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/computer/tests/test_glm_computer.py +0 -0
  276. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/elicitation.py +0 -0
  277. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/__init__.py +0 -0
  278. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/base.py +0 -0
  279. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/pyautogui.py +0 -0
  280. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/tests/__init__.py +0 -0
  281. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/tests/test_base_executor.py +0 -0
  282. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/tests/test_pyautogui_executor.py +0 -0
  283. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/executors/xdo.py +0 -0
  284. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/__init__.py +0 -0
  285. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/base.py +0 -0
  286. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/gemini.py +0 -0
  287. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/gemini_read_many.py +0 -0
  288. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/glob.py +0 -0
  289. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/grep.py +0 -0
  290. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/list.py +0 -0
  291. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/read.py +0 -0
  292. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/__init__.py +0 -0
  293. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/test_glob.py +0 -0
  294. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/test_grep.py +0 -0
  295. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/test_list.py +0 -0
  296. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/test_read.py +0 -0
  297. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/filesystem/tests/test_read_many.py +0 -0
  298. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/__init__.py +0 -0
  299. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/config.py +0 -0
  300. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/grounded_tool.py +0 -0
  301. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/grounder.py +0 -0
  302. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/tests/__init__.py +0 -0
  303. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/grounding/tests/test_grounded_tool.py +0 -0
  304. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/__init__.py +0 -0
  305. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/base.py +0 -0
  306. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/code_execution.py +0 -0
  307. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/google_search.py +0 -0
  308. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/tool_search.py +0 -0
  309. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/url_context.py +0 -0
  310. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/web_fetch.py +0 -0
  311. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/hosted/web_search.py +0 -0
  312. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/jupyter.py +0 -0
  313. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/__init__.py +0 -0
  314. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/base.py +0 -0
  315. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/claude.py +0 -0
  316. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/gemini.py +0 -0
  317. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/session.py +0 -0
  318. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/tests/__init__.py +0 -0
  319. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/tests/test_claude.py +0 -0
  320. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/tests/test_gemini.py +0 -0
  321. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/memory/tests/test_session.py +0 -0
  322. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/native_types.py +0 -0
  323. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/playwright.py +0 -0
  324. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/response.py +0 -0
  325. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/submit.py +0 -0
  326. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/__init__.py +0 -0
  327. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_agent_tool.py +0 -0
  328. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_base.py +0 -0
  329. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_elicitation.py +0 -0
  330. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_init.py +0 -0
  331. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_jupyter_tool.py +0 -0
  332. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_native_tool_e2e.py +0 -0
  333. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_native_types.py +0 -0
  334. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_playwright_tool.py +0 -0
  335. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_response.py +0 -0
  336. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_submit.py +0 -0
  337. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_tools.py +0 -0
  338. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_tools_init.py +0 -0
  339. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_types.py +0 -0
  340. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/tests/test_utils.py +0 -0
  341. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/types.py +0 -0
  342. {hud_python-0.5.36 → hud_python-0.5.37}/hud/tools/utils.py +0 -0
  343. {hud_python-0.5.36 → hud_python-0.5.37}/hud/types.py +0 -0
  344. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/__init__.py +0 -0
  345. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/env.py +0 -0
  346. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/hud_console.py +0 -0
  347. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/mcp.py +0 -0
  348. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/pretty_errors.py +0 -0
  349. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/serialization.py +0 -0
  350. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/strict_schema.py +0 -0
  351. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/__init__.py +0 -0
  352. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/test_init.py +0 -0
  353. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/test_pretty_errors.py +0 -0
  354. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/test_serialization.py +0 -0
  355. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tests/test_tool_shorthand.py +0 -0
  356. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/tool_shorthand.py +0 -0
  357. {hud_python-0.5.36 → hud_python-0.5.37}/hud/utils/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hud-python
3
- Version: 0.5.36
3
+ Version: 0.5.37
4
4
  Summary: SDK for the HUD platform.
5
5
  Project-URL: Homepage, https://github.com/hud-evals/hud-python
6
6
  Project-URL: Bug Tracker, https://github.com/hud-evals/hud-python/issues
@@ -38,6 +38,7 @@ from .dev import dev_command # noqa: E402
38
38
  from .eval import eval_command # noqa: E402
39
39
  from .init import init_command # noqa: E402
40
40
  from .link import link_command # noqa: E402
41
+ from .login import login_command # noqa: E402
41
42
  from .models import models_command # noqa: E402
42
43
  from .push import push_command # noqa: E402
43
44
  from .rl import rl_run_command, rl_status_command # noqa: E402
@@ -52,6 +53,7 @@ app.command(name="dev", context_settings=_EXTRA_ARGS)(dev_command)
52
53
  app.command(name="build", context_settings=_EXTRA_ARGS)(build_command)
53
54
  app.command(name="deploy")(deploy_command)
54
55
  app.command(name="link", hidden=True)(link_command)
56
+ app.command(name="login")(login_command)
55
57
  app.command(name="eval")(eval_command)
56
58
  app.command(name="push", hidden=True)(push_command)
57
59
  app.command(name="init")(init_command)
@@ -0,0 +1,293 @@
1
+ """``hud login`` — Browser-based login for the HUD CLI.
2
+
3
+ Implements the OAuth 2.0 Device Authorization Grant (RFC 8628) against the
4
+ HUD platform so users can authenticate without copy-pasting an API key:
5
+
6
+ Use ``--quiet`` / ``-q`` to print the URL instead of opening a browser
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import contextlib
12
+ import socket
13
+ import time
14
+ import webbrowser
15
+ from typing import Any
16
+
17
+ import httpx
18
+ import typer
19
+ from rich.panel import Panel
20
+ from rich.text import Text
21
+
22
+ from hud.settings import settings
23
+ from hud.utils.hud_console import HUDConsole
24
+
25
+ from .utils.config import get_user_env_path, set_env_values
26
+
27
+ DEVICE_CODE_PATH = "/auth/device/code"
28
+ DEVICE_TOKEN_PATH = "/auth/device/token" # noqa: S105 — URL path, not a secret
29
+
30
+ # Fallback poll interval if the server doesn't send one.
31
+ DEFAULT_POLL_INTERVAL = 5
32
+ # Max wall-clock time to wait for the user to confirm.
33
+ DEFAULT_EXPIRES_IN = 600
34
+
35
+
36
+ def _client_name() -> str:
37
+ try:
38
+ return socket.gethostname() or "unknown host"
39
+ except Exception:
40
+ return "unknown host"
41
+
42
+
43
+ def _client_version() -> str:
44
+ try:
45
+ from hud import __version__
46
+
47
+ return str(__version__)
48
+ except Exception:
49
+ return "unknown"
50
+
51
+
52
+ def _api_base_url() -> str:
53
+ return settings.hud_api_url.rstrip("/")
54
+
55
+
56
+ def _fallback_web_url() -> str:
57
+ return settings.hud_web_url.rstrip("/")
58
+
59
+
60
+ def _extract_error_code(response: httpx.Response) -> str | None:
61
+ """Pull RFC 8628 error codes out of a non-200 response.
62
+
63
+ The backend wraps errors as ``{"detail": {"error": "authorization_pending"}}``
64
+ via FastAPI's ``HTTPException``. Be defensive in case the shape changes.
65
+ """
66
+ try:
67
+ body: Any = response.json()
68
+ except Exception:
69
+ return None
70
+ if isinstance(body, dict):
71
+ detail = body.get("detail")
72
+ if isinstance(detail, dict) and isinstance(detail.get("error"), str):
73
+ return detail["error"]
74
+ if isinstance(body.get("error"), str):
75
+ return body["error"]
76
+ return None
77
+
78
+
79
+ def _request_device_code(client: httpx.Client, hud_console: HUDConsole) -> dict[str, Any]:
80
+ """Call ``POST /auth/device/code`` and return the parsed response body."""
81
+ try:
82
+ response = client.post(
83
+ f"{_api_base_url()}{DEVICE_CODE_PATH}",
84
+ json={
85
+ "client_name": _client_name(),
86
+ "client_version": _client_version(),
87
+ },
88
+ timeout=30.0,
89
+ )
90
+ except httpx.RequestError as exc:
91
+ hud_console.error(f"Failed to reach HUD API: {exc}")
92
+ hud_console.info(f"HUD_API_URL={_api_base_url()}")
93
+ raise typer.Exit(1) from exc
94
+
95
+ if response.status_code != 200:
96
+ hud_console.error(f"HUD API returned {response.status_code} when starting login.")
97
+ with contextlib.suppress(Exception):
98
+ hud_console.info(response.text[:500])
99
+ raise typer.Exit(1)
100
+
101
+ try:
102
+ return response.json()
103
+ except Exception as exc:
104
+ hud_console.error("HUD API returned an invalid response.")
105
+ raise typer.Exit(1) from exc
106
+
107
+
108
+ def _display_login_prompt(
109
+ hud_console: HUDConsole,
110
+ *,
111
+ user_code: str,
112
+ verification_uri: str,
113
+ verification_uri_complete: str,
114
+ quiet: bool,
115
+ ) -> None:
116
+ """Show the big 'open this URL / enter this code' card."""
117
+ body = Text()
118
+ body.append("Verification code: ", style="dim")
119
+ body.append(f"{user_code}\n\n", style="bold cyan")
120
+ if quiet:
121
+ body.append("Open this URL in your browser:\n", style="dim")
122
+ else:
123
+ body.append("Opening this URL in your browser:\n", style="dim")
124
+ body.append(f" {verification_uri_complete}\n\n")
125
+ body.append("Or visit ", style="dim")
126
+ body.append(verification_uri, style="")
127
+ body.append(" and enter the code manually.", style="dim")
128
+
129
+ hud_console.console.print(
130
+ Panel(
131
+ body,
132
+ title="[bold]hud login[/bold]",
133
+ border_style="cyan",
134
+ padding=(1, 2),
135
+ )
136
+ )
137
+
138
+
139
+ def _poll_for_token(
140
+ client: httpx.Client,
141
+ hud_console: HUDConsole,
142
+ *,
143
+ device_code: str,
144
+ interval: int,
145
+ expires_in: int,
146
+ ) -> dict[str, Any]:
147
+ """Poll ``/auth/device/token`` until success, timeout, or fatal error."""
148
+ deadline = time.monotonic() + max(expires_in, 30)
149
+ current_interval = max(interval, 1)
150
+
151
+ with hud_console.console.status(
152
+ "[cyan]Waiting for confirmation in your browser...[/cyan]",
153
+ spinner="dots",
154
+ ):
155
+ while time.monotonic() < deadline:
156
+ # Sleep first so we don't hammer the server on the initial tick
157
+ # before the user has had a chance to click "Connect CLI".
158
+ time.sleep(current_interval)
159
+
160
+ try:
161
+ response = client.post(
162
+ f"{_api_base_url()}{DEVICE_TOKEN_PATH}",
163
+ json={"device_code": device_code},
164
+ timeout=30.0,
165
+ )
166
+ except httpx.RequestError:
167
+ # Transient network error — keep polling.
168
+ continue
169
+
170
+ if response.status_code == 200:
171
+ try:
172
+ return response.json()
173
+ except Exception as exc: # pragma: no cover — server misbehaving
174
+ hud_console.error("HUD API returned an invalid token response.")
175
+ raise typer.Exit(1) from exc
176
+
177
+ error = _extract_error_code(response)
178
+ if error == "authorization_pending":
179
+ continue
180
+ if error == "slow_down":
181
+ current_interval += 5
182
+ continue
183
+ if error == "expired_token":
184
+ hud_console.error(
185
+ "Login code expired before you confirmed. Run 'hud login' to try again."
186
+ )
187
+ raise typer.Exit(1)
188
+ if error == "access_denied":
189
+ hud_console.error("Login was denied in the browser.")
190
+ raise typer.Exit(1)
191
+
192
+ # Unknown 4xx/5xx — treat as transient unless it's an obvious fatal.
193
+ if 500 <= response.status_code < 600:
194
+ continue
195
+
196
+ hud_console.error(f"Unexpected response from HUD API ({response.status_code}).")
197
+ with contextlib.suppress(Exception):
198
+ hud_console.info(response.text[:500])
199
+ raise typer.Exit(1)
200
+
201
+ hud_console.error("Login timed out. Run 'hud login' to try again.")
202
+ raise typer.Exit(1)
203
+
204
+
205
+ def _persist_api_key(hud_console: HUDConsole, api_key: str) -> None:
206
+ """Write ``HUD_API_KEY`` into ``~/.hud/.env``."""
207
+ try:
208
+ path = set_env_values({"HUD_API_KEY": api_key})
209
+ except Exception as exc:
210
+ hud_console.error(f"Failed to write {get_user_env_path()}: {exc}")
211
+ hud_console.info("You can set the key manually with:")
212
+ hud_console.info(f" hud set HUD_API_KEY={api_key}")
213
+ raise typer.Exit(1) from exc
214
+
215
+ hud_console.success("Saved API key to user config")
216
+ hud_console.info(f"Location: {path}")
217
+
218
+
219
+ def login_command(
220
+ quiet: bool = typer.Option(
221
+ False,
222
+ "--quiet",
223
+ "-q",
224
+ help="Don't try to open a browser; print the verification URL instead.",
225
+ ),
226
+ ) -> None:
227
+ """Authenticate with the HUD platform.
228
+
229
+ [not dim]Opens a browser to hud.ai, confirms your identity, and stores a
230
+ freshly-minted API key in ~/.hud/.env.
231
+
232
+ Examples:
233
+ hud login
234
+ hud login --quiet[/not dim]
235
+ """
236
+ hud_console = HUDConsole()
237
+
238
+ # -- Device authorization grant -----------------------------------------
239
+ try:
240
+ with httpx.Client() as client:
241
+ device = _request_device_code(client, hud_console)
242
+
243
+ device_code = device["device_code"]
244
+ user_code = device["user_code"]
245
+ verification_uri = device.get("verification_uri") or f"{_fallback_web_url()}/device"
246
+ verification_uri_complete = (
247
+ device.get("verification_uri_complete")
248
+ or f"{_fallback_web_url()}/device?code={user_code}"
249
+ )
250
+ interval = int(device.get("interval") or DEFAULT_POLL_INTERVAL)
251
+ expires_in = int(device.get("expires_in") or DEFAULT_EXPIRES_IN)
252
+
253
+ _display_login_prompt(
254
+ hud_console,
255
+ user_code=user_code,
256
+ verification_uri=verification_uri,
257
+ verification_uri_complete=verification_uri_complete,
258
+ quiet=quiet,
259
+ )
260
+
261
+ if not quiet:
262
+ with contextlib.suppress(Exception):
263
+ webbrowser.open(verification_uri_complete, new=2)
264
+
265
+ token = _poll_for_token(
266
+ client,
267
+ hud_console,
268
+ device_code=device_code,
269
+ interval=interval,
270
+ expires_in=expires_in,
271
+ )
272
+ except KeyboardInterrupt:
273
+ hud_console.info("\nLogin cancelled.")
274
+ raise typer.Exit(130) from None
275
+
276
+ # -- Persist and report -------------------------------------------------
277
+ key = token.get("api_key")
278
+ if not isinstance(key, str) or not key:
279
+ hud_console.error("HUD API returned a login response without an API key.")
280
+ raise typer.Exit(1)
281
+
282
+ _persist_api_key(hud_console, key)
283
+
284
+ user_info = token.get("user") or {}
285
+ team_info = token.get("team") or {}
286
+ user_email = user_info.get("email") if isinstance(user_info, dict) else None
287
+ team_name = team_info.get("name") if isinstance(team_info, dict) else None
288
+
289
+ if user_email:
290
+ hud_console.info(f"Logged in as {user_email}")
291
+ if team_name:
292
+ hud_console.info(f"Team: {team_name}")
293
+ hud_console.info("You're all set, try 'hud eval --help'.")
@@ -61,12 +61,12 @@ class TestIncrementVersion:
61
61
  def test_increment_minor(self):
62
62
  """Test incrementing minor version."""
63
63
  assert increment_version("1.2.3", "minor") == "1.3.0"
64
- assert increment_version("0.5.36", "minor") == "0.6.0"
64
+ assert increment_version("0.5.37", "minor") == "0.6.0"
65
65
 
66
66
  def test_increment_major(self):
67
67
  """Test incrementing major version."""
68
68
  assert increment_version("1.2.3", "major") == "2.0.0"
69
- assert increment_version("0.5.36", "major") == "1.0.0"
69
+ assert increment_version("0.5.37", "major") == "1.0.0"
70
70
 
71
71
  def test_increment_with_v_prefix(self):
72
72
  """Test incrementing version with v prefix."""
@@ -777,7 +777,6 @@ class TestColumnInference:
777
777
  defs = _build_column_definitions(specs)
778
778
  assert defs is not None
779
779
  assert defs["difficulty"]["type"] == "text"
780
- assert defs["score"]["type"] == "number"
781
780
 
782
781
  def test_build_column_definitions_empty(self) -> None:
783
782
  from hud.cli.sync import _build_column_definitions
@@ -15,7 +15,8 @@ def require_api_key(action: str = "perform this action") -> str:
15
15
  hud_console = HUDConsole()
16
16
  hud_console.error("No HUD API key found")
17
17
  hud_console.info(f"A HUD API key is required to {action}.")
18
- hud_console.info("Get your key at: https://hud.ai/settings")
18
+ hud_console.info("Run: hud login")
19
+ hud_console.info("Or get your key at: https://hud.ai/settings")
19
20
  hud_console.info("Set it via: hud set HUD_API_KEY=your-key-here")
20
21
  raise typer.Exit(1)
21
22
  return settings.api_key
@@ -76,6 +76,12 @@ class Settings(BaseSettings):
76
76
  validation_alias="HUD_API_URL",
77
77
  )
78
78
 
79
+ hud_web_url: str = Field(
80
+ default="https://hud.ai",
81
+ description="Base URL of the HUD web app (used as a fallback for CLI login)",
82
+ validation_alias="HUD_WEB_URL",
83
+ )
84
+
79
85
  hud_gateway_url: str = Field(
80
86
  default="https://inference.hud.ai",
81
87
  description="Base URL for the HUD inference gateway",
@@ -5,4 +5,4 @@ def test_import():
5
5
  """Test that the package can be imported."""
6
6
  import hud
7
7
 
8
- assert hud.__version__ == "0.5.36"
8
+ assert hud.__version__ == "0.5.37"
@@ -4,4 +4,4 @@ Version information for the HUD SDK.
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- __version__ = "0.5.36"
7
+ __version__ = "0.5.37"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hud-python"
3
- version = "0.5.36"
3
+ version = "0.5.37"
4
4
  description = "SDK for the HUD platform."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11, <3.13"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes