deepagents-cli 0.0.38__tar.gz → 0.0.39__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 (198) hide show
  1. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/CHANGELOG.md +13 -0
  2. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/PKG-INFO +1 -1
  3. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_version.py +1 -1
  4. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/app.py +56 -8
  5. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/command_registry.py +50 -11
  6. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/deploy/bundler.py +110 -10
  7. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/deploy/commands.py +4 -1
  8. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/deploy/config.py +141 -1
  9. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/deploy/templates.py +111 -1
  10. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/main.py +60 -12
  11. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/model_config.py +10 -1
  12. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/ui.py +3 -0
  13. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/update_check.py +76 -17
  14. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/autocomplete.py +16 -9
  15. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/chat_input.py +207 -5
  16. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/pyproject.toml +1 -1
  17. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/test_bundler.py +207 -16
  18. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/test_config.py +148 -1
  19. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_app.py +166 -0
  20. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_args.py +16 -0
  21. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_autocomplete.py +36 -8
  22. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_chat_input.py +230 -0
  23. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_command_registry.py +14 -9
  24. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_offload.py +2 -2
  25. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_reload.py +1 -1
  26. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_skill_invocation.py +12 -11
  27. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_update_check.py +228 -0
  28. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/uv.lock +9 -9
  29. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/.gitignore +0 -0
  30. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/DEV.md +0 -0
  31. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/Makefile +0 -0
  32. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/README.md +0 -0
  33. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/THREAT_MODEL.md +0 -0
  34. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/__init__.py +0 -0
  35. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/__main__.py +0 -0
  36. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_ask_user_types.py +0 -0
  37. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_cli_context.py +0 -0
  38. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_debug.py +0 -0
  39. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_env_vars.py +0 -0
  40. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_server_config.py +0 -0
  41. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_session_stats.py +0 -0
  42. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/_testing_models.py +0 -0
  43. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/agent.py +0 -0
  44. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/app.tcss +0 -0
  45. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/ask_user.py +0 -0
  46. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/__init__.py +0 -0
  47. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
  48. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
  49. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  50. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  51. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/clipboard.py +0 -0
  52. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/config.py +0 -0
  53. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/configurable_model.py +0 -0
  54. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/default_agent_prompt.md +0 -0
  55. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/deploy/__init__.py +0 -0
  56. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/editor.py +0 -0
  57. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/file_ops.py +0 -0
  58. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/formatting.py +0 -0
  59. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/hooks.py +0 -0
  60. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/input.py +0 -0
  61. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/integrations/__init__.py +0 -0
  62. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/integrations/sandbox_factory.py +0 -0
  63. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/integrations/sandbox_provider.py +0 -0
  64. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/local_context.py +0 -0
  65. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/mcp_tools.py +0 -0
  66. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/mcp_trust.py +0 -0
  67. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/media_utils.py +0 -0
  68. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/non_interactive.py +0 -0
  69. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/offload.py +0 -0
  70. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/output.py +0 -0
  71. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/project_utils.py +0 -0
  72. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/py.typed +0 -0
  73. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/remote_client.py +0 -0
  74. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/server.py +0 -0
  75. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/server_graph.py +0 -0
  76. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/server_manager.py +0 -0
  77. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/sessions.py +0 -0
  78. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/skills/__init__.py +0 -0
  79. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/skills/commands.py +0 -0
  80. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/skills/invocation.py +0 -0
  81. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/skills/load.py +0 -0
  82. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/subagents.py +0 -0
  83. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/system_prompt.md +0 -0
  84. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/textual_adapter.py +0 -0
  85. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/theme.py +0 -0
  86. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/token_state.py +0 -0
  87. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/tool_display.py +0 -0
  88. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/tools.py +0 -0
  89. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/unicode_security.py +0 -0
  90. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/__init__.py +0 -0
  91. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/_links.py +0 -0
  92. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/approval.py +0 -0
  93. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/ask_user.py +0 -0
  94. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/diff.py +0 -0
  95. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/history.py +0 -0
  96. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/loading.py +0 -0
  97. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/mcp_viewer.py +0 -0
  98. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/message_store.py +0 -0
  99. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/messages.py +0 -0
  100. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/model_selector.py +0 -0
  101. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/notification_settings.py +0 -0
  102. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/status.py +0 -0
  103. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/theme_selector.py +0 -0
  104. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/thread_selector.py +0 -0
  105. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/tool_renderers.py +0 -0
  106. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/tool_widgets.py +0 -0
  107. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/deepagents_cli/widgets/welcome.py +0 -0
  108. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/deploy-content-writer/.env.example +0 -0
  109. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
  110. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
  111. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/deploy-content-writer/user/context.md +0 -0
  112. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/deploy-content-writer/user/preferences.md +0 -0
  113. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/arxiv-search/SKILL.md +0 -0
  114. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  115. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/langgraph-docs/SKILL.md +0 -0
  116. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/skill-creator/SKILL.md +0 -0
  117. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  118. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  119. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/examples/skills/web-research/SKILL.md +0 -0
  120. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/images/cli.png +0 -0
  121. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/scripts/check_imports.py +0 -0
  122. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/scripts/debug_server.sh +0 -0
  123. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/scripts/install.sh +0 -0
  124. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/README.md +0 -0
  125. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/__init__.py +0 -0
  126. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/__init__.py +0 -0
  127. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  128. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  129. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/conftest.py +0 -0
  130. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/test_acp_mode.py +0 -0
  131. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/test_compact_resume.py +0 -0
  132. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/test_sandbox_factory.py +0 -0
  133. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/integration_tests/test_sandbox_operations.py +0 -0
  134. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/__init__.py +0 -0
  135. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/conftest.py +0 -0
  136. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/__init__.py +0 -0
  137. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/test_commands.py +0 -0
  138. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/skills/__init__.py +0 -0
  139. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_commands.py +0 -0
  140. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_load.py +0 -0
  141. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_skills_json.py +0 -0
  142. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_agent.py +0 -0
  143. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_agent_friendly.py +0 -0
  144. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_approval.py +0 -0
  145. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_ask_user.py +0 -0
  146. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  147. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_charset.py +0 -0
  148. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_compact_tool.py +0 -0
  149. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_config.py +0 -0
  150. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_configurable_model.py +0 -0
  151. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_debug.py +0 -0
  152. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_editor.py +0 -0
  153. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_end_to_end.py +0 -0
  154. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_env_vars.py +0 -0
  155. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_exception_handling.py +0 -0
  156. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_file_ops.py +0 -0
  157. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_history.py +0 -0
  158. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_hooks.py +0 -0
  159. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_imports.py +0 -0
  160. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_input_parsing.py +0 -0
  161. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_links.py +0 -0
  162. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_loading.py +0 -0
  163. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_local_context.py +0 -0
  164. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_main.py +0 -0
  165. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_main_acp_mode.py +0 -0
  166. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_main_args.py +0 -0
  167. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_tools.py +0 -0
  168. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_trust.py +0 -0
  169. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_viewer.py +0 -0
  170. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_media_utils.py +0 -0
  171. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_message_store.py +0 -0
  172. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_messages.py +0 -0
  173. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_config.py +0 -0
  174. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_selector.py +0 -0
  175. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_switch.py +0 -0
  176. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_non_interactive.py +0 -0
  177. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_output.py +0 -0
  178. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_remote_client.py +0 -0
  179. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_sandbox_factory.py +0 -0
  180. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_server.py +0 -0
  181. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_config.py +0 -0
  182. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_graph.py +0 -0
  183. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_helpers.py +0 -0
  184. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_manager.py +0 -0
  185. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_sessions.py +0 -0
  186. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_shell_allow_list.py +0 -0
  187. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_status.py +0 -0
  188. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_subagents.py +0 -0
  189. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_textual_adapter.py +0 -0
  190. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_theme.py +0 -0
  191. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_thread_selector.py +0 -0
  192. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_token_tracker.py +0 -0
  193. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_ui.py +0 -0
  194. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_unicode_security.py +0 -0
  195. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_version.py +0 -0
  196. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/test_welcome.py +0 -0
  197. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/tools/__init__.py +0 -0
  198. {deepagents_cli-0.0.38 → deepagents_cli-0.0.39}/tests/unit_tests/tools/test_fetch_url.py +0 -0
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.39](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.38...deepagents-cli==0.0.39) (2026-04-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** inline argument hints for slash commands ([#2181](https://github.com/langchain-ai/deepagents/issues/2181)) ([6b58e06](https://github.com/langchain-ai/deepagents/commit/6b58e06b06f6fb360d85c54eac31953d1e47dd7a))
9
+ * **cli:** subagents for `deepagents deploy` ([#2786](https://github.com/langchain-ai/deepagents/issues/2786)) ([7dd5565](https://github.com/langchain-ai/deepagents/commit/7dd5565e30ab91a2cd2ca10fcd227e590451f13c))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **cli:** throttle update notification to once per day and fix teardown banner ([#2764](https://github.com/langchain-ai/deepagents/issues/2764)) ([ba31294](https://github.com/langchain-ai/deepagents/commit/ba31294b733d4ef542d18830eec6df30cfa0d23f))
15
+
3
16
  ## [0.0.38](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.37...deepagents-cli==0.0.38) (2026-04-15)
4
17
 
5
18
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.0.38
3
+ Version: 0.0.39
4
4
  Summary: Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities.
5
5
  Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
6
6
  Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
@@ -1,6 +1,6 @@
1
1
  """Version information and lightweight constants for `deepagents-cli`."""
2
2
 
3
- __version__ = "0.0.38" # x-release-please-version
3
+ __version__ = "0.0.39" # x-release-please-version
4
4
 
5
5
  DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/cli"
6
6
  """URL for `deepagents-cli` documentation."""
@@ -1439,7 +1439,7 @@ class DeepAgentsApp(App):
1439
1439
  )
1440
1440
 
1441
1441
  available, latest = await asyncio.to_thread(is_update_available)
1442
- if not available:
1442
+ if not available or latest is None:
1443
1443
  return
1444
1444
 
1445
1445
  self._update_available = (True, latest)
@@ -1447,7 +1447,7 @@ class DeepAgentsApp(App):
1447
1447
  logger.debug("Background update check failed", exc_info=True)
1448
1448
  return
1449
1449
 
1450
- # Phase 2: auto-update or notify (failures surfaced to user)
1450
+ # Phase 2: auto-update or notify
1451
1451
  try:
1452
1452
  from deepagents_cli._version import __version__ as cli_version
1453
1453
 
@@ -1475,6 +1475,14 @@ class DeepAgentsApp(App):
1475
1475
  markup=False,
1476
1476
  )
1477
1477
  else:
1478
+ from deepagents_cli.update_check import (
1479
+ mark_update_notified,
1480
+ should_notify_update,
1481
+ )
1482
+
1483
+ if not await asyncio.to_thread(should_notify_update, latest):
1484
+ return
1485
+
1478
1486
  cmd = upgrade_command()
1479
1487
  self.notify(
1480
1488
  f"Update available: v{latest} (current: v{cli_version}). "
@@ -1484,13 +1492,15 @@ class DeepAgentsApp(App):
1484
1492
  timeout=15,
1485
1493
  markup=False,
1486
1494
  )
1495
+ await asyncio.to_thread(mark_update_notified, latest)
1487
1496
  except Exception:
1488
- logger.warning("Auto-update failed unexpectedly", exc_info=True)
1489
- self.notify(
1490
- "Update failed unexpectedly.",
1491
- severity="warning",
1492
- timeout=10,
1493
- )
1497
+ logger.warning("Update check/notify failed unexpectedly", exc_info=True)
1498
+ if is_auto_update_enabled():
1499
+ self.notify(
1500
+ "Auto-update failed unexpectedly.",
1501
+ severity="warning",
1502
+ timeout=10,
1503
+ )
1494
1504
 
1495
1505
  async def _show_whats_new(self) -> None:
1496
1506
  """Show a 'what's new' banner on the first launch after an upgrade."""
@@ -2763,6 +2773,15 @@ class DeepAgentsApp(App):
2763
2773
  elif cmd == "/remember" or cmd.startswith("/remember "):
2764
2774
  # Convenience alias for /skill:remember — shorter and discoverable
2765
2775
  # before skill loading completes.
2776
+ if not await self._has_conversation_messages():
2777
+ await self._mount_message(UserMessage(command))
2778
+ await self._mount_message(
2779
+ AppMessage(
2780
+ "Nothing to remember yet. Start a conversation first,"
2781
+ " then use /remember to capture learnings."
2782
+ )
2783
+ )
2784
+ return
2766
2785
  args = command.strip()[len("/remember") :].strip()
2767
2786
  rewritten = f"/skill:remember {args}" if args else "/skill:remember"
2768
2787
  await self._handle_skill_command(rewritten)
@@ -3043,6 +3062,35 @@ class DeepAgentsApp(App):
3043
3062
  skill_name, args = parse_skill_command(command)
3044
3063
  await self._invoke_skill(skill_name, args, command=command)
3045
3064
 
3065
+ async def _has_conversation_messages(self) -> bool:
3066
+ """Check whether the current thread has at least one human message.
3067
+
3068
+ Returns:
3069
+ `True` if the conversation contains a `HumanMessage`, `False`
3070
+ otherwise. On transient errors (network, corrupt state) returns
3071
+ `True` so that `/remember` is not blocked with a misleading
3072
+ "nothing to remember" message.
3073
+ """
3074
+ if not self._agent:
3075
+ return False
3076
+ try:
3077
+ from langchain_core.messages import HumanMessage
3078
+
3079
+ config: RunnableConfig = {
3080
+ "configurable": {"thread_id": self._lc_thread_id},
3081
+ }
3082
+ state = await self._agent.aget_state(config)
3083
+ if not state or not state.values:
3084
+ return False
3085
+ messages = state.values.get("messages", [])
3086
+ return any(isinstance(m, HumanMessage) for m in messages)
3087
+ except Exception:
3088
+ logger.warning(
3089
+ "Failed to check conversation messages; allowing /remember to proceed",
3090
+ exc_info=True,
3091
+ )
3092
+ return True
3093
+
3046
3094
  async def _get_conversation_token_count(self) -> int | None:
3047
3095
  """Return the approximate conversation-only token count.
3048
3096
 
@@ -1,7 +1,7 @@
1
1
  """Unified slash-command registry.
2
2
 
3
3
  Every slash command is declared once as a `SlashCommand` entry in `COMMANDS`.
4
- Bypass-tier frozensets and autocomplete tuples are derived automatically — no
4
+ Bypass-tier frozensets and autocomplete entries are derived automatically — no
5
5
  other file should hard-code command metadata.
6
6
  """
7
7
 
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
 
10
10
  from dataclasses import dataclass
11
11
  from enum import StrEnum
12
- from typing import TYPE_CHECKING
12
+ from typing import TYPE_CHECKING, NamedTuple
13
13
 
14
14
  if TYPE_CHECKING:
15
15
  from deepagents_cli.skills.load import ExtendedSkillMetadata
@@ -50,9 +50,26 @@ class SlashCommand:
50
50
  hidden_keywords: str = ""
51
51
  """Space-separated terms for fuzzy matching (never displayed)."""
52
52
 
53
+ argument_hint: str = ""
54
+ """Placeholder text for autocomplete when the command accepts args."""
55
+
53
56
  aliases: tuple[str, ...] = ()
54
57
  """Alternative names (e.g. `("/q",)` for `/quit`)."""
55
58
 
59
+ def to_entry(self) -> CommandEntry:
60
+ """Project this command into a `CommandEntry` for autocomplete.
61
+
62
+ Returns:
63
+ A `CommandEntry` carrying only the fields the autocomplete
64
+ layer needs.
65
+ """
66
+ return CommandEntry(
67
+ name=self.name,
68
+ description=self.description,
69
+ hidden_keywords=self.hidden_keywords,
70
+ argument_hint=self.argument_hint,
71
+ )
72
+
56
73
 
57
74
  COMMANDS: tuple[SlashCommand, ...] = (
58
75
  SlashCommand(
@@ -94,11 +111,13 @@ COMMANDS: tuple[SlashCommand, ...] = (
94
111
  name="/remember",
95
112
  description="Update memory and skills from conversation",
96
113
  bypass_tier=BypassTier.QUEUED,
114
+ argument_hint="[context]",
97
115
  ),
98
116
  SlashCommand( # Static alias; not auto-generated from skill discovery
99
117
  name="/skill-creator",
100
118
  description="Guide for creating effective agent skills",
101
119
  bypass_tier=BypassTier.QUEUED,
120
+ argument_hint="[task]",
102
121
  ),
103
122
  SlashCommand(
104
123
  name="/threads",
@@ -228,13 +247,28 @@ ALL_CLASSIFIED: frozenset[str] = (
228
247
 
229
248
 
230
249
  # ---------------------------------------------------------------------------
231
- # Autocomplete tuples
250
+ # Autocomplete entries
232
251
  # ---------------------------------------------------------------------------
233
252
 
234
- SLASH_COMMANDS: list[tuple[str, str, str]] = [
235
- (cmd.name, cmd.description, cmd.hidden_keywords) for cmd in COMMANDS
236
- ]
237
- """`(name, description, hidden_keywords)` tuples for `SlashCommandController`."""
253
+
254
+ class CommandEntry(NamedTuple):
255
+ """A single autocomplete entry for the slash-command controller."""
256
+
257
+ name: str
258
+ """Canonical command name (e.g. `/quit`)."""
259
+
260
+ description: str
261
+ """Short user-facing description."""
262
+
263
+ hidden_keywords: str
264
+ """Space-separated terms for fuzzy matching (never displayed)."""
265
+
266
+ argument_hint: str
267
+ """Placeholder text shown when the command accepts arguments (e.g. `[context]`)."""
268
+
269
+
270
+ SLASH_COMMANDS: list[CommandEntry] = [cmd.to_entry() for cmd in COMMANDS]
271
+ """Autocomplete entries derived from `COMMANDS` for `SlashCommandController`."""
238
272
 
239
273
 
240
274
  def parse_skill_command(command: str) -> tuple[str, str]:
@@ -271,8 +305,8 @@ appear as `/skill:model`).
271
305
 
272
306
  def build_skill_commands(
273
307
  skills: list[ExtendedSkillMetadata],
274
- ) -> list[tuple[str, str, str]]:
275
- """Build autocomplete tuples for discovered skills.
308
+ ) -> list[CommandEntry]:
309
+ """Build autocomplete entries for discovered skills.
276
310
 
277
311
  Each skill becomes a `/skill:<name>` entry with its description
278
312
  and the skill name as a hidden keyword for fuzzy matching.
@@ -285,10 +319,15 @@ def build_skill_commands(
285
319
  skills: List of discovered skill metadata.
286
320
 
287
321
  Returns:
288
- List of `(name, description, hidden_keywords)` tuples.
322
+ List of `CommandEntry` instances.
289
323
  """
290
324
  return [
291
- (f"/skill:{skill['name']}", skill["description"], skill["name"])
325
+ CommandEntry(
326
+ name=f"/skill:{skill['name']}",
327
+ description=skill["description"],
328
+ hidden_keywords=skill["name"],
329
+ argument_hint="",
330
+ )
292
331
  for skill in skills
293
332
  if skill["name"] not in _STATIC_SKILL_ALIASES
294
333
  ]
@@ -27,6 +27,7 @@ import json
27
27
  import logging
28
28
  import shutil
29
29
  from pathlib import Path
30
+ from typing import Any
30
31
 
31
32
  from deepagents_cli.deploy.config import (
32
33
  AGENTS_MD_FILENAME,
@@ -34,12 +35,15 @@ from deepagents_cli.deploy.config import (
34
35
  SKILLS_DIRNAME,
35
36
  USER_DIRNAME,
36
37
  DeployConfig,
38
+ SubAgentProject,
39
+ load_subagents,
37
40
  )
38
41
  from deepagents_cli.deploy.templates import (
39
42
  DEPLOY_GRAPH_TEMPLATE,
40
43
  MCP_TOOLS_TEMPLATE,
41
44
  PYPROJECT_TEMPLATE,
42
45
  SANDBOX_BLOCKS,
46
+ SYNC_SUBAGENTS_TEMPLATE,
43
47
  )
44
48
 
45
49
  logger = logging.getLogger(__name__)
@@ -77,7 +81,7 @@ def bundle(
77
81
  system_prompt = agents_md_path.read_text(encoding="utf-8")
78
82
 
79
83
  # 2. Build and write the seed payload: memory (AGENTS.md) + skills/.
80
- seed = _build_seed(config, project_root, system_prompt)
84
+ seed = _build_seed(project_root, system_prompt)
81
85
  (build_dir / "_seed.json").write_text(
82
86
  json.dumps(seed, indent=2, ensure_ascii=False),
83
87
  encoding="utf-8",
@@ -104,35 +108,89 @@ def bundle(
104
108
  shutil.copy2(env_src, build_dir / ".env")
105
109
  logger.info("Copied %s → .env", env_src)
106
110
 
107
- # 4. Render deploy_graph.py.
111
+ # 4. Load subagents (needed for both deploy_graph.py and pyproject.toml).
112
+ sync_subagents = load_subagents(project_root)
113
+
114
+ # 5. Render deploy_graph.py.
108
115
  has_user_memories = (project_root / USER_DIRNAME).is_dir()
116
+ has_sync_subagents = bool(sync_subagents)
109
117
  (build_dir / "deploy_graph.py").write_text(
110
118
  _render_deploy_graph(
111
119
  config,
112
120
  mcp_present=mcp_present,
113
121
  has_user_memories=has_user_memories,
122
+ has_sync_subagents=has_sync_subagents,
114
123
  ),
115
124
  encoding="utf-8",
116
125
  )
117
126
  logger.info("Generated deploy_graph.py")
118
127
 
119
- # 5. Render langgraph.json.
128
+ # 6. Render langgraph.json.
120
129
  (build_dir / "langgraph.json").write_text(
121
130
  _render_langgraph_json(env_present=env_present),
122
131
  encoding="utf-8",
123
132
  )
124
133
 
125
- # 6. Render pyproject.toml.
134
+ # 7. Render pyproject.toml.
135
+ subagent_model_providers: list[str] = []
136
+ has_subagent_mcp = False
137
+ for sa in sync_subagents.values():
138
+ model = sa.config.agent.model
139
+ if ":" in model:
140
+ subagent_model_providers.append(model.split(":", 1)[0])
141
+ if (sa.root / MCP_FILENAME).is_file():
142
+ has_subagent_mcp = True
143
+
126
144
  (build_dir / "pyproject.toml").write_text(
127
- _render_pyproject(config, mcp_present=mcp_present),
145
+ _render_pyproject(
146
+ config,
147
+ mcp_present=mcp_present,
148
+ subagent_model_providers=subagent_model_providers,
149
+ has_subagent_mcp=has_subagent_mcp,
150
+ ),
128
151
  encoding="utf-8",
129
152
  )
130
153
 
131
154
  return build_dir
132
155
 
133
156
 
157
+ def _build_subagent_seed(subagent: SubAgentProject) -> dict:
158
+ """Build the seed entry for a single sync subagent."""
159
+ sa_root = subagent.root
160
+ agent = subagent.config.agent
161
+
162
+ memories: dict[str, str] = {
163
+ f"/{AGENTS_MD_FILENAME}": (sa_root / AGENTS_MD_FILENAME).read_text(
164
+ encoding="utf-8"
165
+ ),
166
+ }
167
+
168
+ skills: dict[str, str] = {}
169
+ skills_dir = sa_root / SKILLS_DIRNAME
170
+ if skills_dir.is_dir():
171
+ for f in sorted(skills_dir.rglob("*")):
172
+ if f.is_file() and not f.name.startswith("."):
173
+ rel = f.relative_to(skills_dir).as_posix()
174
+ skills[f"/{rel}"] = f.read_text(encoding="utf-8")
175
+
176
+ mcp_path = sa_root / MCP_FILENAME
177
+ mcp = None
178
+ if mcp_path.is_file():
179
+ mcp = json.loads(mcp_path.read_text(encoding="utf-8"))
180
+
181
+ return {
182
+ "config": {
183
+ "name": agent.name,
184
+ "description": agent.description,
185
+ "model": agent.model,
186
+ },
187
+ "memories": memories,
188
+ "skills": skills,
189
+ "mcp": mcp,
190
+ }
191
+
192
+
134
193
  def _build_seed(
135
- config: DeployConfig, # noqa: ARG001
136
194
  project_root: Path,
137
195
  system_prompt: str,
138
196
  ) -> dict:
@@ -172,18 +230,28 @@ def _build_seed(
172
230
  )
173
231
  user_memories[f"/{AGENTS_MD_FILENAME}"] = content
174
232
 
175
- return {
233
+ seed: dict = {
176
234
  "memories": memories,
177
235
  "skills": skills,
178
236
  "user_memories": user_memories,
179
237
  }
180
238
 
239
+ # Sync subagents.
240
+ sync_subagents = load_subagents(project_root)
241
+ if sync_subagents:
242
+ seed["subagents"] = {
243
+ name: _build_subagent_seed(sa) for name, sa in sync_subagents.items()
244
+ }
245
+
246
+ return seed
247
+
181
248
 
182
249
  def _render_deploy_graph(
183
250
  config: DeployConfig,
184
251
  *,
185
252
  mcp_present: bool,
186
253
  has_user_memories: bool = False,
254
+ has_sync_subagents: bool = False,
187
255
  ) -> str:
188
256
  """Render the generated `deploy_graph.py`."""
189
257
  provider = config.sandbox.provider
@@ -199,6 +267,16 @@ def _render_deploy_graph(
199
267
  mcp_tools_block = ""
200
268
  mcp_tools_load_call = "pass # no MCP servers configured"
201
269
 
270
+ if has_sync_subagents:
271
+ sync_subagents_block = SYNC_SUBAGENTS_TEMPLATE
272
+ sync_subagents_load_call = (
273
+ "all_subagents.extend("
274
+ "await _build_sync_subagents(seed, store, assistant_id))"
275
+ )
276
+ else:
277
+ sync_subagents_block = ""
278
+ sync_subagents_load_call = "pass # no sync subagents"
279
+
202
280
  return DEPLOY_GRAPH_TEMPLATE.format(
203
281
  model=config.agent.model,
204
282
  sandbox_template=config.sandbox.template,
@@ -209,6 +287,8 @@ def _render_deploy_graph(
209
287
  mcp_tools_load_call=mcp_tools_load_call,
210
288
  default_assistant_id=config.agent.name,
211
289
  has_user_memories=has_user_memories,
290
+ sync_subagents_block=sync_subagents_block,
291
+ sync_subagents_load_call=sync_subagents_load_call,
212
292
  )
213
293
 
214
294
 
@@ -224,7 +304,13 @@ def _render_langgraph_json(*, env_present: bool) -> str:
224
304
  return json.dumps(data, indent=2) + "\n"
225
305
 
226
306
 
227
- def _render_pyproject(config: DeployConfig, *, mcp_present: bool) -> str:
307
+ def _render_pyproject(
308
+ config: DeployConfig,
309
+ *,
310
+ mcp_present: bool,
311
+ subagent_model_providers: list[str] | None = None,
312
+ has_subagent_mcp: bool = False,
313
+ ) -> str:
228
314
  """Render the deployment package's `pyproject.toml`.
229
315
 
230
316
  Deps are inferred — the user never writes them. We add:
@@ -241,7 +327,13 @@ def _render_pyproject(config: DeployConfig, *, mcp_present: bool) -> str:
241
327
  if provider_prefix and provider_prefix in _MODEL_PROVIDER_DEPS:
242
328
  deps.append(_MODEL_PROVIDER_DEPS[provider_prefix])
243
329
 
244
- if mcp_present:
330
+ # Add deps for subagent model providers.
331
+ for sp in subagent_model_providers or []:
332
+ dep = _MODEL_PROVIDER_DEPS.get(sp)
333
+ if dep and dep not in deps:
334
+ deps.append(dep)
335
+
336
+ if mcp_present or has_subagent_mcp:
245
337
  deps.append("langchain-mcp-adapters")
246
338
 
247
339
  _, partner_pkg = SANDBOX_BLOCKS.get(config.sandbox.provider, (None, None))
@@ -259,7 +351,7 @@ def _render_pyproject(config: DeployConfig, *, mcp_present: bool) -> str:
259
351
  def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
260
352
  """Print a human-readable summary of what was bundled."""
261
353
  seed_path = build_dir / "_seed.json"
262
- seed: dict[str, dict[str, str]] = {"memories": {}, "skills": {}}
354
+ seed: dict[str, Any] = {"memories": {}, "skills": {}}
263
355
  if seed_path.exists():
264
356
  try:
265
357
  seed = json.loads(seed_path.read_text(encoding="utf-8"))
@@ -294,6 +386,14 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
294
386
  if (build_dir / "_mcp.json").exists():
295
387
  print("\n MCP config: _mcp.json")
296
388
 
389
+ # Subagent summary.
390
+ sync_subagents = seed.get("subagents", {})
391
+ if sync_subagents:
392
+ print(f"\n Subagents ({len(sync_subagents)}):")
393
+ for name, sa_data in sync_subagents.items():
394
+ desc = sa_data.get("config", {}).get("description", "")
395
+ print(f" {name} \u2014 {desc}")
396
+
297
397
  print(f"\n Sandbox: {config.sandbox.provider}")
298
398
  print(f"\n Build directory: {build_dir}")
299
399
  generated = sorted(f.name for f in build_dir.iterdir() if f.is_file())
@@ -6,6 +6,7 @@ Registered with the CLI via `setup_deploy_parsers` in `main.py`.
6
6
  from __future__ import annotations
7
7
 
8
8
  import argparse
9
+ import os
9
10
  import subprocess
10
11
  import tempfile
11
12
  from pathlib import Path
@@ -402,12 +403,14 @@ def _run_langgraph_deploy(build_dir: Path, *, name: str) -> None:
402
403
 
403
404
  config_path = str(build_dir / "langgraph.json")
404
405
  cmd = ["langgraph", "deploy", "-c", config_path, "--name", name, "--verbose"]
406
+ env = os.environ.copy()
407
+ env["LANGGRAPH_CLI_ANALYTICS_SOURCE"] = "deepagents"
405
408
 
406
409
  print("Deploying to LangSmith Deployments...")
407
410
  print(f"Running: {' '.join(cmd)}")
408
411
  print()
409
412
 
410
- result = subprocess.run(cmd, cwd=str(build_dir), check=False)
413
+ result = subprocess.run(cmd, cwd=str(build_dir), check=False, env=env)
411
414
 
412
415
  if result.returncode != 0:
413
416
  print(f"\nDeployment failed (exit code {result.returncode}).")