hud-python 0.6.0__tar.gz → 0.6.2__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 (235) hide show
  1. {hud_python-0.6.0 → hud_python-0.6.2}/.gitignore +4 -0
  2. {hud_python-0.6.0 → hud_python-0.6.2}/PKG-INFO +1 -1
  3. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/rl-training/README.md +15 -7
  4. hud_python-0.6.2/hud/cli/init.py +147 -0
  5. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/models.py +4 -0
  6. hud_python-0.6.2/hud/cli/presets.py +139 -0
  7. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_init.py +3 -3
  8. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/gateway.py +1 -0
  9. {hud_python-0.6.0 → hud_python-0.6.2}/hud/version.py +1 -1
  10. {hud_python-0.6.0 → hud_python-0.6.2}/pyproject.toml +1 -1
  11. hud_python-0.6.0/hud/cli/init.py +0 -76
  12. {hud_python-0.6.0 → hud_python-0.6.2}/LICENSE +0 -0
  13. {hud_python-0.6.0 → hud_python-0.6.2}/README.md +0 -0
  14. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/a2a-chat/README.md +0 -0
  15. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/a2a-chat/pyproject.toml +0 -0
  16. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/codex-coding/README.md +0 -0
  17. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/codex-coding/pyproject.toml +0 -0
  18. {hud_python-0.6.0 → hud_python-0.6.2}/cookbooks/rl-training/pyproject.toml +0 -0
  19. {hud_python-0.6.0 → hud_python-0.6.2}/hud/__init__.py +0 -0
  20. {hud_python-0.6.0 → hud_python-0.6.2}/hud/__main__.py +0 -0
  21. {hud_python-0.6.0 → hud_python-0.6.2}/hud/_legacy.py +0 -0
  22. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/__init__.py +0 -0
  23. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/base.py +0 -0
  24. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/browser_use/__init__.py +0 -0
  25. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/browser_use/agent.py +0 -0
  26. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/__init__.py +0 -0
  27. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/agent.py +0 -0
  28. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/sdk/__init__.py +0 -0
  29. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/sdk/agent.py +0 -0
  30. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/sdk/computer_mcp.py +0 -0
  31. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/__init__.py +0 -0
  32. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/base.py +0 -0
  33. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/coding.py +0 -0
  34. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/computer.py +0 -0
  35. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/hosted.py +0 -0
  36. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/mcp_proxy.py +0 -0
  37. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/settings.py +0 -0
  38. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/tests/__init__.py +0 -0
  39. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/claude/tools/tests/test_computer.py +0 -0
  40. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/__init__.py +0 -0
  41. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/agent.py +0 -0
  42. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/settings.py +0 -0
  43. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/__init__.py +0 -0
  44. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/base.py +0 -0
  45. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/coding.py +0 -0
  46. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/computer.py +0 -0
  47. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/filesystem.py +0 -0
  48. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/hosted.py +0 -0
  49. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/mcp_proxy.py +0 -0
  50. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/tests/__init__.py +0 -0
  51. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/gemini/tools/tests/test_computer.py +0 -0
  52. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/misc/__init__.py +0 -0
  53. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/misc/response_automation.py +0 -0
  54. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/__init__.py +0 -0
  55. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/agent.py +0 -0
  56. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/__init__.py +0 -0
  57. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/apply_patch.py +0 -0
  58. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/base.py +0 -0
  59. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/coding.py +0 -0
  60. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/computer.py +0 -0
  61. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/hosted.py +0 -0
  62. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/mcp_proxy.py +0 -0
  63. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/strict_schema.py +0 -0
  64. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/tests/__init__.py +0 -0
  65. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/tests/test_computer.py +0 -0
  66. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai/tools/tests/test_strict_schema.py +0 -0
  67. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/__init__.py +0 -0
  68. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/agent.py +0 -0
  69. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/tools/__init__.py +0 -0
  70. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/tools/base.py +0 -0
  71. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/tools/filesystem.py +0 -0
  72. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/openai_compatible/tools/mcp_proxy.py +0 -0
  73. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/robot/__init__.py +0 -0
  74. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/robot/_types.py +0 -0
  75. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/robot/adapter.py +0 -0
  76. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/robot/agent.py +0 -0
  77. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/robot/model.py +0 -0
  78. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/__init__.py +0 -0
  79. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_apply_patch.py +0 -0
  80. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_base.py +0 -0
  81. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_claude_agent.py +0 -0
  82. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_claude_sdk_agent.py +0 -0
  83. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_gemini_agent.py +0 -0
  84. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_openai_agent.py +0 -0
  85. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_openai_compatible_agent.py +0 -0
  86. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_provider_native_tools.py +0 -0
  87. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_tool_agent.py +0 -0
  88. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tests/test_trace.py +0 -0
  89. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tool_agent.py +0 -0
  90. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/__init__.py +0 -0
  91. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/base.py +0 -0
  92. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/hosted.py +0 -0
  93. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/mcp.py +0 -0
  94. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/rfb.py +0 -0
  95. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/tools/ssh.py +0 -0
  96. {hud_python-0.6.0 → hud_python-0.6.2}/hud/agents/types.py +0 -0
  97. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/__init__.py +0 -0
  98. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/base.py +0 -0
  99. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/cdp.py +0 -0
  100. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/filetracking.py +0 -0
  101. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/mcp.py +0 -0
  102. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/rfb.py +0 -0
  103. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/robot.py +0 -0
  104. {hud_python-0.6.0 → hud_python-0.6.2}/hud/capabilities/ssh.py +0 -0
  105. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/__init__.py +0 -0
  106. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/__main__.py +0 -0
  107. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/cancel.py +0 -0
  108. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/client.py +0 -0
  109. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/deploy.py +0 -0
  110. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/eval.py +0 -0
  111. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/login.py +0 -0
  112. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/serve.py +0 -0
  113. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/sync.py +0 -0
  114. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/task.py +0 -0
  115. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/templates.py +0 -0
  116. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/__init__.py +0 -0
  117. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_cli_init.py +0 -0
  118. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_cli_main.py +0 -0
  119. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_cli_more_wrappers.py +0 -0
  120. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_deploy.py +0 -0
  121. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_eval_bedrock.py +0 -0
  122. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_eval_config.py +0 -0
  123. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_main_module.py +0 -0
  124. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/tests/test_sync_export.py +0 -0
  125. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/__init__.py +0 -0
  126. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/api.py +0 -0
  127. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/build_display.py +0 -0
  128. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/build_logs.py +0 -0
  129. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/config.py +0 -0
  130. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/context.py +0 -0
  131. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/display.py +0 -0
  132. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/jobs.py +0 -0
  133. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/registry.py +0 -0
  134. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/source.py +0 -0
  135. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tasks.py +0 -0
  136. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/__init__.py +0 -0
  137. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_build_display.py +0 -0
  138. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_config.py +0 -0
  139. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_context.py +0 -0
  140. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_registry.py +0 -0
  141. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_source.py +0 -0
  142. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_tasks.py +0 -0
  143. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/tests/test_version_check.py +0 -0
  144. {hud_python-0.6.0 → hud_python-0.6.2}/hud/cli/utils/version_check.py +0 -0
  145. {hud_python-0.6.0 → hud_python-0.6.2}/hud/clients/__init__.py +0 -0
  146. {hud_python-0.6.0 → hud_python-0.6.2}/hud/clients/client.py +0 -0
  147. {hud_python-0.6.0 → hud_python-0.6.2}/hud/clients/tests/__init__.py +0 -0
  148. {hud_python-0.6.0 → hud_python-0.6.2}/hud/clients/tests/test_connect.py +0 -0
  149. {hud_python-0.6.0 → hud_python-0.6.2}/hud/conftest.py +0 -0
  150. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/__init__.py +0 -0
  151. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/env.py +0 -0
  152. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/file_tracker.py +0 -0
  153. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/file_tracking.py +0 -0
  154. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/legacy.py +0 -0
  155. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/robot/__init__.py +0 -0
  156. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/robot/bridge.py +0 -0
  157. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/robot/endpoint.py +0 -0
  158. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/robot/sim_runner.py +0 -0
  159. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/server.py +0 -0
  160. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/__init__.py +0 -0
  161. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/conftest.py +0 -0
  162. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_capability_backing.py +0 -0
  163. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_file_tracker.py +0 -0
  164. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_file_tracking.py +0 -0
  165. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_legacy.py +0 -0
  166. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_loader.py +0 -0
  167. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_manifest.py +0 -0
  168. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_server.py +0 -0
  169. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/tests/test_tunnel.py +0 -0
  170. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/utils.py +0 -0
  171. {hud_python-0.6.0 → hud_python-0.6.2}/hud/environment/workspace.py +0 -0
  172. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/__init__.py +0 -0
  173. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/chat.py +0 -0
  174. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/file_tracking.py +0 -0
  175. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/job.py +0 -0
  176. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/run.py +0 -0
  177. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/runtime.py +0 -0
  178. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/sync.py +0 -0
  179. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/task.py +0 -0
  180. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/taskset.py +0 -0
  181. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/__init__.py +0 -0
  182. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_chat.py +0 -0
  183. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_docker_provider.py +0 -0
  184. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_file_tracking_observer.py +0 -0
  185. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_hosted.py +0 -0
  186. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_job.py +0 -0
  187. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_rollout.py +0 -0
  188. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_sync.py +0 -0
  189. {hud_python-0.6.0 → hud_python-0.6.2}/hud/eval/tests/test_task.py +0 -0
  190. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/__init__.py +0 -0
  191. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/base.py +0 -0
  192. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/bash.py +0 -0
  193. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/combine.py +0 -0
  194. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/judge.py +0 -0
  195. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/results.py +0 -0
  196. {hud_python-0.6.0 → hud_python-0.6.2}/hud/graders/text.py +0 -0
  197. {hud_python-0.6.0 → hud_python-0.6.2}/hud/patches/__init__.py +0 -0
  198. {hud_python-0.6.0 → hud_python-0.6.2}/hud/patches/mcp_patches.py +0 -0
  199. {hud_python-0.6.0 → hud_python-0.6.2}/hud/patches/tests/__init__.py +0 -0
  200. {hud_python-0.6.0 → hud_python-0.6.2}/hud/patches/tests/test_warnings.py +0 -0
  201. {hud_python-0.6.0 → hud_python-0.6.2}/hud/patches/warnings.py +0 -0
  202. {hud_python-0.6.0 → hud_python-0.6.2}/hud/py.typed +0 -0
  203. {hud_python-0.6.0 → hud_python-0.6.2}/hud/server.py +0 -0
  204. {hud_python-0.6.0 → hud_python-0.6.2}/hud/settings.py +0 -0
  205. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/__init__.py +0 -0
  206. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/context.py +0 -0
  207. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/exporter.py +0 -0
  208. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/filetracking.py +0 -0
  209. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/instrument.py +0 -0
  210. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/span.py +0 -0
  211. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/tests/__init__.py +0 -0
  212. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/tests/test_exporter.py +0 -0
  213. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/tests/test_filetracking.py +0 -0
  214. {hud_python-0.6.0 → hud_python-0.6.2}/hud/telemetry/tests/test_instrument.py +0 -0
  215. {hud_python-0.6.0 → hud_python-0.6.2}/hud/train/__init__.py +0 -0
  216. {hud_python-0.6.0 → hud_python-0.6.2}/hud/train/base.py +0 -0
  217. {hud_python-0.6.0 → hud_python-0.6.2}/hud/train/client.py +0 -0
  218. {hud_python-0.6.0 → hud_python-0.6.2}/hud/train/types.py +0 -0
  219. {hud_python-0.6.0 → hud_python-0.6.2}/hud/types.py +0 -0
  220. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/__init__.py +0 -0
  221. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/exceptions.py +0 -0
  222. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/hints.py +0 -0
  223. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/hud_console.py +0 -0
  224. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/modules.py +0 -0
  225. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/platform.py +0 -0
  226. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/requests.py +0 -0
  227. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/serialization.py +0 -0
  228. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/__init__.py +0 -0
  229. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_exceptions.py +0 -0
  230. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_hints.py +0 -0
  231. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_hud_console.py +0 -0
  232. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_platform.py +0 -0
  233. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_requests.py +0 -0
  234. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/tests/test_serialization.py +0 -0
  235. {hud_python-0.6.0 → hud_python-0.6.2}/hud/utils/time.py +0 -0
@@ -7,6 +7,10 @@ __pycache__
7
7
  .pytest_cache
8
8
  dist/
9
9
  build/
10
+ # The broad build/ rule above also matches docs/v6/build/, which is real docs
11
+ # content (linked from docs.json). Keep tracking it so docs.hud.ai/v6/build/*
12
+ # does not 404.
13
+ !docs/v6/build/
10
14
  *.egg-info/
11
15
  uv.lock
12
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hud-python
3
- Version: 0.6.0
3
+ Version: 0.6.2
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
@@ -18,22 +18,30 @@ each `optim_step` closes the on-policy loop.
18
18
 
19
19
  ## Run
20
20
 
21
- Needs `HUD_API_KEY` and `HUD_MODEL` (a trainable gateway model).
21
+ Needs `HUD_API_KEY` (from your environment or `.env`). List the gateway models
22
+ on your account, pick a trainable one (the **Trainable** column marks them), and
23
+ set it as the `MODEL` constant at the top of `simple_train.py` /
24
+ `ppo_custom_loss.py`:
25
+
26
+ ```bash
27
+ hud models list # Name | Model (API) | ID | Provider | Agent | Trainable
28
+ ```
22
29
 
23
30
  **Train on a deployed taskset (the real flow).** You've built a taskset and
24
- pushed it (`hud deploy` + `hud sync`); now train on it. Point `HUD_TASKSET` at it
25
- and rollouts run on **remote HUD boxes** — nothing local:
31
+ pushed it (`hud deploy` + `hud sync`); now train on it. Set the `TASKSET`
32
+ constant in `common.py` to its name/id and rollouts run on **remote HUD
33
+ boxes** — nothing local:
26
34
 
27
35
  ```bash
28
- HUD_MODEL=<trainable-model> HUD_TASKSET=<taskset-name-or-id> uv run simple_train.py --steps 10
29
- HUD_MODEL=<trainable-model> HUD_TASKSET=<taskset-name-or-id> uv run ppo_custom_loss.py --steps 10
36
+ uv run simple_train.py --steps 10
37
+ uv run ppo_custom_loss.py --steps 10
30
38
  ```
31
39
 
32
- **Quickstart (self-contained).** Leave `HUD_TASKSET` unset and a tiny local
40
+ **Quickstart (self-contained).** Leave `TASKSET` empty and a tiny local
33
41
  arithmetic taskset runs against the bundled `env.py`:
34
42
 
35
43
  ```bash
36
- HUD_MODEL=<trainable-model> uv run simple_train.py --steps 10
44
+ uv run simple_train.py --steps 10
37
45
  ```
38
46
 
39
47
  The swap is `common.py`'s `load_taskset_and_runtime()` — `Taskset.from_api(name)`
@@ -0,0 +1,147 @@
1
+ """``hud init``: scaffold a new HUD environment package.
2
+
3
+ By default (or in a non-interactive shell) it writes a minimal local scaffold —
4
+ no network, no API key. With ``--preset`` (or via the interactive picker) it
5
+ downloads one of the starter environments from GitHub instead — the same set the
6
+ platform's *environments/new* flow offers. See :mod:`hud.cli.presets`.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import shutil
12
+ import sys
13
+ import tarfile
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ import httpx
18
+ import typer
19
+
20
+ from hud.utils.hud_console import HUDConsole
21
+
22
+ from .presets import ENVIRONMENT_PRESETS, PRESETS_BY_ID, EnvironmentPreset, materialize_preset
23
+ from .templates import DOCKERFILE_HUD, ENV_PY, PYPROJECT_TOML, TASKS_PY
24
+
25
+ _LOCAL_SCAFFOLD = "__local__"
26
+
27
+
28
+ def _python_name(name: str) -> str:
29
+ """Normalize a package name into a Python-identifier-ish env name."""
30
+ name = name.replace("-", "_").replace(" ", "_")
31
+ return "".join(c if c.isalnum() or c == "_" else "_" for c in name)
32
+
33
+
34
+ def _resolve_preset(preset: str | None, hud_console: HUDConsole) -> EnvironmentPreset | None:
35
+ """Pick the starter: an explicit ``--preset`` id, an interactive choice, or
36
+ ``None`` for the minimal local scaffold."""
37
+ if preset is not None:
38
+ chosen = PRESETS_BY_ID.get(preset)
39
+ if chosen is None:
40
+ available = ", ".join(PRESETS_BY_ID)
41
+ hud_console.error(f"Unknown preset {preset!r}. Available: {available}")
42
+ raise typer.Exit(1)
43
+ return chosen
44
+
45
+ # No flag: pick interactively when we have a TTY, else the local scaffold.
46
+ if not (sys.stdin.isatty() and sys.stdout.isatty()):
47
+ return None
48
+
49
+ choices: list[str | dict[str, Any]] = [
50
+ {"name": "Minimal (local scaffold, no download)", "value": _LOCAL_SCAFFOLD},
51
+ *({"name": f"{p.name} — {p.description}", "value": p.id} for p in ENVIRONMENT_PRESETS),
52
+ ]
53
+ selected = hud_console.select("Choose a starter", choices, default=0)
54
+ return None if selected == _LOCAL_SCAFFOLD else PRESETS_BY_ID[selected]
55
+
56
+
57
+ def _write_local_scaffold(target: Path, env_name: str, hud_console: HUDConsole) -> None:
58
+ """Write the bundled minimal env package into ``target``."""
59
+ files = {
60
+ "pyproject.toml": PYPROJECT_TOML.format(name=env_name.replace("_", "-")),
61
+ "env.py": ENV_PY.format(env_name=env_name),
62
+ "tasks.py": TASKS_PY.format(env_name=env_name),
63
+ "Dockerfile.hud": DOCKERFILE_HUD,
64
+ }
65
+ target.mkdir(parents=True, exist_ok=True)
66
+ for filename, content in files.items():
67
+ (target / filename).write_text(content)
68
+ hud_console.status_item(filename, "✓")
69
+
70
+
71
+ def init_command(
72
+ name: str = typer.Argument(..., help="Environment name (directory to create)"),
73
+ directory: str = typer.Option(".", "--dir", "-d", help="Parent directory"),
74
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing files"),
75
+ preset: str | None = typer.Option(
76
+ None,
77
+ "--preset",
78
+ "-p",
79
+ help="Starter preset to download from GitHub (e.g. blank, coding, browser, "
80
+ "deepresearch, rubrics, remote-browser). Omit for an interactive picker; in a "
81
+ "non-interactive shell, omitting it writes the minimal local scaffold.",
82
+ ),
83
+ ) -> None:
84
+ """🚀 Create a new HUD environment package.
85
+
86
+ [not dim]With no --preset, writes a minimal local scaffold (env.py, tasks.py,
87
+ Dockerfile.hud, pyproject.toml) — or, in a TTY, lets you pick a starter. With
88
+ --preset, downloads that starter from GitHub.
89
+
90
+ Examples:
91
+ hud init my-env # interactive picker (or local scaffold)
92
+ hud init my-env --preset coding # download the coding starter
93
+ hud init my-env --dir envs # create ./envs/my-env[/not dim]
94
+ """
95
+ hud_console = HUDConsole()
96
+
97
+ target = Path(directory) / name
98
+ if target.exists() and any(target.iterdir()) and not force:
99
+ hud_console.error(f"{target} already exists and is not empty (use --force)")
100
+ raise typer.Exit(1)
101
+
102
+ chosen = _resolve_preset(preset, hud_console)
103
+
104
+ hud_console.header(f"HUD Init: {name}")
105
+ if chosen is not None:
106
+ hud_console.info(f"Downloading {chosen.owner}/{chosen.repo} …")
107
+ created = not target.exists()
108
+ try:
109
+ materialize_preset(chosen, target)
110
+ except (httpx.HTTPError, tarfile.TarError, ValueError, OSError) as exc:
111
+ # Don't leave a half-written tree behind — it would trip the
112
+ # non-empty-directory guard on the next run. Only remove a directory
113
+ # this run created (never a dir the user already had).
114
+ if created and target.exists():
115
+ shutil.rmtree(target, ignore_errors=True)
116
+ hud_console.error(f"Failed to fetch preset {chosen.id!r}: {exc}")
117
+ raise typer.Exit(1) from exc
118
+ hud_console.status_item(f"{chosen.owner}/{chosen.repo}", "✓")
119
+ else:
120
+ _write_local_scaffold(target, _python_name(name), hud_console)
121
+
122
+ hud_console.section_title("Next Steps")
123
+ hud_console.info("")
124
+ hud_console.command_example(f"cd {target}", "1. Enter the package")
125
+ hud_console.info("")
126
+ if chosen is not None:
127
+ hud_console.info("2. Read the README for this starter's setup + tasks.")
128
+ hud_console.info("")
129
+ hud_console.command_example("hud eval tasks.py claude", "3. Run an agent over the tasks")
130
+ hud_console.info("")
131
+ hud_console.info("4. Deploy for scale")
132
+ hud_console.info(" hud deploy, then run many evals in parallel.")
133
+ else:
134
+ hud_console.info("2. Define task definitions in env.py")
135
+ hud_console.info(" A @env.template is an async generator: it yields a prompt, then")
136
+ hud_console.info(" (after the agent answers) yields a reward.")
137
+ hud_console.info("")
138
+ hud_console.info("3. List the tasks to run in tasks.py")
139
+ hud_console.info(" Call a task with args to bind a runnable Task.")
140
+ hud_console.info("")
141
+ hud_console.command_example("hud eval tasks.py claude", "4. Run an agent over them")
142
+ hud_console.info("")
143
+ hud_console.info("5. Deploy for scale")
144
+ hud_console.info(" hud deploy, then run many evals in parallel.")
145
+ hud_console.info("")
146
+ hud_console.info("Tip: Install the HUD skill so your coding agent can help you build:")
147
+ hud_console.command_example("npx skills add docs.hud.ai", "Install HUD skill")
@@ -56,14 +56,18 @@ def list_models(
56
56
  table = Table()
57
57
  table.add_column("Name", style="cyan")
58
58
  table.add_column("Model (API)", style="green")
59
+ table.add_column("ID", style="blue", no_wrap=True)
59
60
  table.add_column("Provider", style="yellow")
60
61
  table.add_column("Agent", style="magenta")
62
+ table.add_column("Trainable", style="green", justify="center")
61
63
  for model in models_list:
62
64
  table.add_row(
63
65
  model.name or model.id or "-",
64
66
  model.model_name or model.id or "-",
67
+ model.id or "-",
65
68
  model.provider.name or "-",
66
69
  model.sdk_agent_type or "-",
70
+ "✓" if model.is_trainable else "",
67
71
  )
68
72
  console.print(table)
69
73
  console.print(f"\n[dim]Gateway: {settings.hud_gateway_url}[/dim]")
@@ -0,0 +1,139 @@
1
+ """Starter presets for ``hud init`` — the same set offered by the platform's
2
+ *environments/new* flow.
3
+
4
+ Each preset is a standalone public GitHub repo under ``hud-evals``. ``hud init``
5
+ downloads the repo tarball (no ``git`` required) and extracts it into the target
6
+ directory. Keep this list in sync with the frontend's ``ENVIRONMENT_TEMPLATES``
7
+ (``app/(auth)/environments/components/EnvironmentTemplates.tsx``).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import io
13
+ import os
14
+ import tarfile
15
+ from dataclasses import dataclass
16
+ from typing import TYPE_CHECKING
17
+
18
+ import httpx
19
+
20
+ if TYPE_CHECKING:
21
+ from pathlib import Path
22
+
23
+
24
+ @dataclass(frozen=True, slots=True)
25
+ class EnvironmentPreset:
26
+ """A starter environment sourced from a public GitHub repo."""
27
+
28
+ id: str
29
+ name: str
30
+ description: str
31
+ owner: str
32
+ repo: str
33
+
34
+
35
+ ENVIRONMENT_PRESETS: tuple[EnvironmentPreset, ...] = (
36
+ EnvironmentPreset(
37
+ "blank",
38
+ "Blank",
39
+ "Minimal starting point for a custom environment.",
40
+ "hud-evals",
41
+ "hud-blank",
42
+ ),
43
+ EnvironmentPreset(
44
+ "browser",
45
+ "Browser",
46
+ "Local browser automation environment.",
47
+ "hud-evals",
48
+ "hud-browser",
49
+ ),
50
+ EnvironmentPreset(
51
+ "deepresearch",
52
+ "Deep Research",
53
+ "Deep research environment with Exa search integration.",
54
+ "hud-evals",
55
+ "hud-deepresearch",
56
+ ),
57
+ EnvironmentPreset(
58
+ "cua",
59
+ "Computer Use",
60
+ "Computer-use agent (CUA) desktop environment.",
61
+ "hud-evals",
62
+ "cua-template",
63
+ ),
64
+ EnvironmentPreset(
65
+ "autonomous-businesses",
66
+ "Autonomous Businesses",
67
+ "Autonomous business simulation environment.",
68
+ "hud-evals",
69
+ "autonomous-businesses-template",
70
+ ),
71
+ EnvironmentPreset(
72
+ "verilog",
73
+ "Verilog",
74
+ "Verilog hardware-design environment.",
75
+ "hud-evals",
76
+ "verilog-template",
77
+ ),
78
+ )
79
+
80
+ PRESETS_BY_ID: dict[str, EnvironmentPreset] = {p.id: p for p in ENVIRONMENT_PRESETS}
81
+
82
+ _TARBALL_TIMEOUT = 60.0
83
+
84
+
85
+ def _is_within(root: Path, path: Path) -> bool:
86
+ try:
87
+ path.relative_to(root)
88
+ return True
89
+ except ValueError:
90
+ return False
91
+
92
+
93
+ def _download_tarball(preset: EnvironmentPreset) -> bytes:
94
+ """Fetch the repo's ``main`` archive from codeload (no API rate limit)."""
95
+ headers: dict[str, str] = {}
96
+ token = os.environ.get("GITHUB_TOKEN")
97
+ if token:
98
+ headers["Authorization"] = f"Bearer {token}"
99
+
100
+ url = f"https://codeload.github.com/{preset.owner}/{preset.repo}/tar.gz/refs/heads/main"
101
+ with httpx.Client(follow_redirects=True, timeout=_TARBALL_TIMEOUT) as client:
102
+ resp = client.get(url, headers=headers)
103
+ resp.raise_for_status()
104
+ return resp.content
105
+
106
+
107
+ def materialize_preset(preset: EnvironmentPreset, target: Path) -> None:
108
+ """Download ``preset``'s repo archive and extract it into ``target``.
109
+
110
+ Uses ``codeload.github.com`` (not the rate-limited API) for the repo's
111
+ ``main`` branch — no ``git`` required. Strips the archive's top-level
112
+ ``<repo>-main/`` component and refuses any entry that would escape ``target``
113
+ (path-traversal guard). Honors ``GITHUB_TOKEN`` if set.
114
+ """
115
+ payload = _download_tarball(preset)
116
+
117
+ target.mkdir(parents=True, exist_ok=True)
118
+ target_root = target.resolve()
119
+ with tarfile.open(fileobj=io.BytesIO(payload), mode="r:gz") as tar:
120
+ for member in tar.getmembers():
121
+ # GitHub wraps everything in a "<repo>-<sha>/" top-level dir; drop it.
122
+ parts = member.name.split("/", 1)
123
+ if len(parts) < 2 or not parts[1]:
124
+ continue
125
+ dest = (target_root / parts[1]).resolve()
126
+ if not _is_within(target_root, dest):
127
+ raise ValueError(f"unsafe path in archive: {member.name!r}")
128
+ if member.isdir():
129
+ dest.mkdir(parents=True, exist_ok=True)
130
+ elif member.isfile():
131
+ dest.parent.mkdir(parents=True, exist_ok=True)
132
+ source = tar.extractfile(member)
133
+ if source is not None:
134
+ dest.write_bytes(source.read())
135
+ # Preserve the archive's executable bits so entrypoints and
136
+ # scripts stay runnable (no-op on Windows).
137
+ if member.mode & 0o111:
138
+ dest.chmod(dest.stat().st_mode | (member.mode & 0o111))
139
+ # Symlinks and other special members are intentionally skipped.
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
14
14
 
15
15
 
16
16
  def test_init_scaffolds_a_runnable_package(tmp_path: Path) -> None:
17
- init_command(name="my-cool-env", directory=str(tmp_path), force=False)
17
+ init_command(name="my-cool-env", directory=str(tmp_path), force=False, preset=None)
18
18
 
19
19
  target = tmp_path / "my-cool-env"
20
20
  assert {p.name for p in target.iterdir()} == {
@@ -36,7 +36,7 @@ def test_init_refuses_to_clobber_nonempty_directory(tmp_path: Path) -> None:
36
36
  (target / "precious.txt").write_text("data")
37
37
 
38
38
  with pytest.raises(typer.Exit):
39
- init_command(name="taken", directory=str(tmp_path), force=False)
39
+ init_command(name="taken", directory=str(tmp_path), force=False, preset=None)
40
40
 
41
41
  assert (target / "precious.txt").read_text() == "data"
42
42
 
@@ -46,6 +46,6 @@ def test_init_force_overwrites_existing_files(tmp_path: Path) -> None:
46
46
  target.mkdir()
47
47
  (target / "env.py").write_text("old")
48
48
 
49
- init_command(name="env", directory=str(tmp_path), force=True)
49
+ init_command(name="env", directory=str(tmp_path), force=True, preset=None)
50
50
 
51
51
  assert "Environment" in (target / "env.py").read_text()
@@ -35,6 +35,7 @@ class GatewayModelInfo(BaseModel):
35
35
  name: str | None = None
36
36
  model_name: str | None = None
37
37
  sdk_agent_type: str | None = None
38
+ is_trainable: bool = False
38
39
  provider: GatewayProviderInfo = Field(default_factory=GatewayProviderInfo)
39
40
 
40
41
 
@@ -4,4 +4,4 @@ Version information for the HUD SDK.
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- __version__ = "0.5.41"
7
+ __version__ = "0.6.2"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hud-python"
3
- version = "0.6.0"
3
+ version = "0.6.2"
4
4
  description = "SDK for the HUD platform."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11, <3.13"
@@ -1,76 +0,0 @@
1
- """``hud init``: scaffold a new HUD environment package.
2
-
3
- Purely local — writes the v6 template files into a fresh directory. No
4
- network, no API key, no prompts.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from pathlib import Path
10
-
11
- import typer
12
-
13
- from hud.utils.hud_console import HUDConsole
14
-
15
- from .templates import DOCKERFILE_HUD, ENV_PY, PYPROJECT_TOML, TASKS_PY
16
-
17
-
18
- def _python_name(name: str) -> str:
19
- """Normalize a package name into a Python-identifier-ish env name."""
20
- name = name.replace("-", "_").replace(" ", "_")
21
- return "".join(c if c.isalnum() or c == "_" else "_" for c in name)
22
-
23
-
24
- def init_command(
25
- name: str = typer.Argument(..., help="Environment name (directory to create)"),
26
- directory: str = typer.Option(".", "--dir", "-d", help="Parent directory"),
27
- force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing files"),
28
- ) -> None:
29
- """🚀 Create a new HUD environment package.
30
-
31
- [not dim]Writes env.py (tasks + capabilities), tasks.py, Dockerfile.hud, and
32
- pyproject.toml into a new directory.
33
-
34
- Examples:
35
- hud init my-env # create ./my-env
36
- hud init my-env --dir envs # create ./envs/my-env[/not dim]
37
- """
38
- hud_console = HUDConsole()
39
-
40
- target = Path(directory) / name
41
- if target.exists() and any(target.iterdir()) and not force:
42
- hud_console.error(f"{target} already exists and is not empty (use --force)")
43
- raise typer.Exit(1)
44
-
45
- env_name = _python_name(name)
46
- files = {
47
- "pyproject.toml": PYPROJECT_TOML.format(name=env_name.replace("_", "-")),
48
- "env.py": ENV_PY.format(env_name=env_name),
49
- "tasks.py": TASKS_PY.format(env_name=env_name),
50
- "Dockerfile.hud": DOCKERFILE_HUD,
51
- }
52
-
53
- hud_console.header(f"HUD Init: {env_name}")
54
- target.mkdir(parents=True, exist_ok=True)
55
- for filename, content in files.items():
56
- (target / filename).write_text(content)
57
- hud_console.status_item(filename, "✓")
58
-
59
- hud_console.section_title("Next Steps")
60
- hud_console.info("")
61
- hud_console.command_example(f"cd {target}", "1. Enter the package")
62
- hud_console.info("")
63
- hud_console.info("2. Define task definitions in env.py")
64
- hud_console.info(" A @env.template is an async generator: it yields a prompt, then")
65
- hud_console.info(" (after the agent answers) yields a reward.")
66
- hud_console.info("")
67
- hud_console.info("3. List the tasks to run in tasks.py")
68
- hud_console.info(" Call a task with args to bind a runnable Task.")
69
- hud_console.info("")
70
- hud_console.command_example("hud eval tasks.py claude", "4. Run an agent over them")
71
- hud_console.info("")
72
- hud_console.info("5. Deploy for scale")
73
- hud_console.info(" hud deploy, then run many evals in parallel.")
74
- hud_console.info("")
75
- hud_console.info("Tip: Install the HUD skill so your coding agent can help you build:")
76
- hud_console.command_example("npx skills add docs.hud.ai", "Install HUD skill")
File without changes
File without changes
File without changes
File without changes
File without changes