deepagents-cli 0.0.36__tar.gz → 0.0.38__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.36 → deepagents_cli-0.0.38}/.gitignore +3 -0
  2. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/CHANGELOG.md +30 -0
  3. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/PKG-INFO +2 -2
  4. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_version.py +1 -1
  5. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/app.py +8 -4
  6. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/config.py +3 -1
  7. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/deploy/__init__.py +3 -0
  8. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/deploy/bundler.py +76 -34
  9. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/deploy/commands.py +61 -48
  10. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/deploy/config.py +61 -30
  11. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/deploy/templates.py +146 -69
  12. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/integrations/sandbox_factory.py +5 -2
  13. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/model_config.py +2 -0
  14. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/message_store.py +34 -10
  15. deepagents_cli-0.0.38/examples/deploy-content-writer/.env.example +2 -0
  16. deepagents_cli-0.0.38/examples/deploy-content-writer/skills/blog-post/SKILL.md +15 -0
  17. deepagents_cli-0.0.38/examples/deploy-content-writer/skills/social-media/SKILL.md +15 -0
  18. deepagents_cli-0.0.38/examples/deploy-content-writer/user/context.md +15 -0
  19. deepagents_cli-0.0.38/examples/deploy-content-writer/user/preferences.md +11 -0
  20. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/pyproject.toml +2 -2
  21. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/test_compact_resume.py +6 -11
  22. deepagents_cli-0.0.38/tests/unit_tests/deploy/test_bundler.py +350 -0
  23. deepagents_cli-0.0.38/tests/unit_tests/deploy/test_commands.py +75 -0
  24. deepagents_cli-0.0.38/tests/unit_tests/deploy/test_config.py +302 -0
  25. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_config.py +4 -4
  26. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_message_store.py +71 -0
  27. deepagents_cli-0.0.38/tests/unit_tests/tools/__init__.py +0 -0
  28. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/uv.lock +92 -92
  29. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/DEV.md +0 -0
  30. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/Makefile +0 -0
  31. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/README.md +0 -0
  32. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/THREAT_MODEL.md +0 -0
  33. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/__init__.py +0 -0
  34. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/__main__.py +0 -0
  35. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_ask_user_types.py +0 -0
  36. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_cli_context.py +0 -0
  37. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_debug.py +0 -0
  38. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_env_vars.py +0 -0
  39. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_server_config.py +0 -0
  40. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_session_stats.py +0 -0
  41. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/_testing_models.py +0 -0
  42. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/agent.py +0 -0
  43. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/app.tcss +0 -0
  44. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/ask_user.py +0 -0
  45. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/built_in_skills/__init__.py +0 -0
  46. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
  47. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
  48. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  49. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  50. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/clipboard.py +0 -0
  51. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/command_registry.py +0 -0
  52. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/configurable_model.py +0 -0
  53. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/default_agent_prompt.md +0 -0
  54. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/editor.py +0 -0
  55. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/file_ops.py +0 -0
  56. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/formatting.py +0 -0
  57. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/hooks.py +0 -0
  58. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/input.py +0 -0
  59. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/integrations/__init__.py +0 -0
  60. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/integrations/sandbox_provider.py +0 -0
  61. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/local_context.py +0 -0
  62. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/main.py +0 -0
  63. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/mcp_tools.py +0 -0
  64. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/mcp_trust.py +0 -0
  65. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/media_utils.py +0 -0
  66. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/non_interactive.py +0 -0
  67. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/offload.py +0 -0
  68. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/output.py +0 -0
  69. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/project_utils.py +0 -0
  70. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/py.typed +0 -0
  71. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/remote_client.py +0 -0
  72. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/server.py +0 -0
  73. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/server_graph.py +0 -0
  74. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/server_manager.py +0 -0
  75. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/sessions.py +0 -0
  76. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/skills/__init__.py +0 -0
  77. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/skills/commands.py +0 -0
  78. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/skills/invocation.py +0 -0
  79. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/skills/load.py +0 -0
  80. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/subagents.py +0 -0
  81. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/system_prompt.md +0 -0
  82. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/textual_adapter.py +0 -0
  83. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/theme.py +0 -0
  84. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/token_state.py +0 -0
  85. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/tool_display.py +0 -0
  86. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/tools.py +0 -0
  87. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/ui.py +0 -0
  88. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/unicode_security.py +0 -0
  89. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/update_check.py +0 -0
  90. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/__init__.py +0 -0
  91. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/_links.py +0 -0
  92. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/approval.py +0 -0
  93. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/ask_user.py +0 -0
  94. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/autocomplete.py +0 -0
  95. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/chat_input.py +0 -0
  96. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/diff.py +0 -0
  97. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/history.py +0 -0
  98. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/loading.py +0 -0
  99. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/mcp_viewer.py +0 -0
  100. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/messages.py +0 -0
  101. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/model_selector.py +0 -0
  102. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/notification_settings.py +0 -0
  103. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/status.py +0 -0
  104. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/theme_selector.py +0 -0
  105. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/thread_selector.py +0 -0
  106. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/tool_renderers.py +0 -0
  107. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/tool_widgets.py +0 -0
  108. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/deepagents_cli/widgets/welcome.py +0 -0
  109. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/arxiv-search/SKILL.md +0 -0
  110. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  111. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/langgraph-docs/SKILL.md +0 -0
  112. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/skill-creator/SKILL.md +0 -0
  113. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  114. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  115. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/examples/skills/web-research/SKILL.md +0 -0
  116. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/images/cli.png +0 -0
  117. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/scripts/check_imports.py +0 -0
  118. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/scripts/debug_server.sh +0 -0
  119. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/scripts/install.sh +0 -0
  120. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/README.md +0 -0
  121. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/__init__.py +0 -0
  122. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/benchmarks/__init__.py +0 -0
  123. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  124. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  125. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/conftest.py +0 -0
  126. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/test_acp_mode.py +0 -0
  127. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/test_sandbox_factory.py +0 -0
  128. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/integration_tests/test_sandbox_operations.py +0 -0
  129. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/__init__.py +0 -0
  130. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/conftest.py +0 -0
  131. {deepagents_cli-0.0.36/tests/unit_tests/tools → deepagents_cli-0.0.38/tests/unit_tests/deploy}/__init__.py +0 -0
  132. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/skills/__init__.py +0 -0
  133. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/skills/test_commands.py +0 -0
  134. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/skills/test_load.py +0 -0
  135. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/skills/test_skills_json.py +0 -0
  136. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_agent.py +0 -0
  137. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_agent_friendly.py +0 -0
  138. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_app.py +0 -0
  139. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_approval.py +0 -0
  140. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_args.py +0 -0
  141. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_ask_user.py +0 -0
  142. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  143. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_autocomplete.py +0 -0
  144. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_charset.py +0 -0
  145. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_chat_input.py +0 -0
  146. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_command_registry.py +0 -0
  147. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_compact_tool.py +0 -0
  148. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_configurable_model.py +0 -0
  149. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_debug.py +0 -0
  150. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_editor.py +0 -0
  151. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_end_to_end.py +0 -0
  152. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_env_vars.py +0 -0
  153. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_exception_handling.py +0 -0
  154. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_file_ops.py +0 -0
  155. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_history.py +0 -0
  156. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_hooks.py +0 -0
  157. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_imports.py +0 -0
  158. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_input_parsing.py +0 -0
  159. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_links.py +0 -0
  160. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_loading.py +0 -0
  161. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_local_context.py +0 -0
  162. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_main.py +0 -0
  163. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_main_acp_mode.py +0 -0
  164. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_main_args.py +0 -0
  165. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_mcp_tools.py +0 -0
  166. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_mcp_trust.py +0 -0
  167. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_mcp_viewer.py +0 -0
  168. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_media_utils.py +0 -0
  169. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_messages.py +0 -0
  170. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_model_config.py +0 -0
  171. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_model_selector.py +0 -0
  172. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_model_switch.py +0 -0
  173. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_non_interactive.py +0 -0
  174. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_offload.py +0 -0
  175. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_output.py +0 -0
  176. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_reload.py +0 -0
  177. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_remote_client.py +0 -0
  178. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_sandbox_factory.py +0 -0
  179. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_server.py +0 -0
  180. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_server_config.py +0 -0
  181. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_server_graph.py +0 -0
  182. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_server_helpers.py +0 -0
  183. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_server_manager.py +0 -0
  184. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_sessions.py +0 -0
  185. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_shell_allow_list.py +0 -0
  186. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_skill_invocation.py +0 -0
  187. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_status.py +0 -0
  188. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_subagents.py +0 -0
  189. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_textual_adapter.py +0 -0
  190. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_theme.py +0 -0
  191. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_thread_selector.py +0 -0
  192. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_token_tracker.py +0 -0
  193. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_ui.py +0 -0
  194. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_unicode_security.py +0 -0
  195. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_update_check.py +0 -0
  196. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_version.py +0 -0
  197. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/test_welcome.py +0 -0
  198. {deepagents_cli-0.0.36 → deepagents_cli-0.0.38}/tests/unit_tests/tools/test_fetch_url.py +0 -0
@@ -212,6 +212,9 @@ __marimo__/
212
212
  #claude
213
213
  .claude
214
214
 
215
+ # Harbor local job output
216
+ jobs/
217
+
215
218
  .idea
216
219
  TEXTUAL_REFACTOR_PLAN.md
217
220
  libs/cli/TEXTUAL_PROGRESS.md
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.38](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.37...deepagents-cli==0.0.38) (2026-04-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** user scoped memory ([#2708](https://github.com/langchain-ai/deepagents/issues/2708)) ([23bfca6](https://github.com/langchain-ai/deepagents/commit/23bfca6e46e6f3e4fba6657d858ddd5a0b06626f))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deepagents:** remove old integration tests ([#2728](https://github.com/langchain-ai/deepagents/issues/2728)) ([6653197](https://github.com/langchain-ai/deepagents/commit/6653197b6cbec6dd1ca23d9f90bc1439ca26e6e5))
14
+
15
+
16
+ ### Performance Improvements
17
+
18
+ * **cli:** `O(1)` message lookups in `MessageStore` ([#2350](https://github.com/langchain-ai/deepagents/issues/2350)) ([d39fd5d](https://github.com/langchain-ai/deepagents/commit/d39fd5d3651fd87d1eea8c02cbef2c2f62449e67))
19
+
20
+ ## [0.0.37](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.36...deepagents-cli==0.0.37) (2026-04-10)
21
+
22
+ ### Features
23
+
24
+ * Permissions for `deepagents deploy` ([#2651](https://github.com/langchain-ai/deepagents/issues/2651)) ([5d93b73](https://github.com/langchain-ai/deepagents/commit/5d93b736af6ffb165f33569233d533ced95a6943))
25
+
26
+ ### Bug Fixes
27
+
28
+ * Add missing model provider deps to `deepagents deploy` bundler [closes [#2647](https://github.com/langchain-ai/deepagents/issues/2647)] ([#2660](https://github.com/langchain-ai/deepagents/issues/2660)) ([b710a69](https://github.com/langchain-ai/deepagents/commit/b710a69b12e49479045eaa54dfb709326473500b))
29
+ * `AGENTS.md` in system prompt twice ([#2652](https://github.com/langchain-ai/deepagents/issues/2652)) ([9052be9](https://github.com/langchain-ai/deepagents/commit/9052be98d9f4ef9b11a88c9b1df3fae5e5ac666c))
30
+ * Harden `deepagents deploy` config parsing and add unit tests ([#2636](https://github.com/langchain-ai/deepagents/issues/2636)) ([0469d14](https://github.com/langchain-ai/deepagents/commit/0469d1429d129e604fc1b622263923162f719314))
31
+ * Load `deepagents deploy` project `.env` before deploy/dev config validation ([#2644](https://github.com/langchain-ai/deepagents/issues/2644)) ([8299091](https://github.com/langchain-ai/deepagents/commit/829909166606f8a9d9571b00da725845bad08da7))
32
+
3
33
  ## [0.0.36](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.35...deepagents-cli==0.0.36) (2026-04-09)
4
34
 
5
35
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.0.36
3
+ Version: 0.0.38
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/
@@ -27,7 +27,7 @@ Classifier: Topic :: Terminals
27
27
  Requires-Python: <4.0,>=3.11
28
28
  Requires-Dist: aiosqlite<1.0.0,>=0.19.0
29
29
  Requires-Dist: deepagents-acp>=0.0.4
30
- Requires-Dist: deepagents==0.5.1
30
+ Requires-Dist: deepagents==0.5.3
31
31
  Requires-Dist: httpx<1.0.0,>=0.28.1
32
32
  Requires-Dist: langchain-anthropic<2.0.0,>=1.4.0
33
33
  Requires-Dist: langchain-google-genai<5.0.0,>=4.2.1
@@ -1,6 +1,6 @@
1
1
  """Version information and lightweight constants for `deepagents-cli`."""
2
2
 
3
- __version__ = "0.0.36" # x-release-please-version
3
+ __version__ = "0.0.38" # 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."""
@@ -1478,7 +1478,7 @@ class DeepAgentsApp(App):
1478
1478
  cmd = upgrade_command()
1479
1479
  self.notify(
1480
1480
  f"Update available: v{latest} (current: v{cli_version}). "
1481
- f"Run: {cmd}\n"
1481
+ f"Run: {cmd}\n\n"
1482
1482
  f"Enable auto-updates: /auto-update",
1483
1483
  severity="information",
1484
1484
  timeout=15,
@@ -1505,11 +1505,15 @@ class DeepAgentsApp(App):
1505
1505
 
1506
1506
  try:
1507
1507
  from deepagents_cli._version import __version__ as cli_version
1508
+ from deepagents_cli.config import _is_editable_install
1509
+
1510
+ if await asyncio.to_thread(_is_editable_install):
1511
+ heading = f"Now running v{cli_version}"
1512
+ else:
1513
+ heading = f"Updated to v{cli_version}"
1508
1514
 
1509
1515
  await self._mount_message(
1510
- AppMessage(
1511
- f"Updated to v{cli_version}\nSee what's new: {CHANGELOG_URL}"
1512
- )
1516
+ AppMessage(f"{heading}\nSee what's new: {CHANGELOG_URL}")
1513
1517
  )
1514
1518
  except Exception:
1515
1519
  logger.debug("What's new banner display failed", exc_info=True)
@@ -1937,7 +1937,9 @@ def _get_provider_kwargs(
1937
1937
  result["api_key"] = api_key
1938
1938
 
1939
1939
  if provider == "openrouter":
1940
- from deepagents._models import check_openrouter_version # noqa: PLC2701
1940
+ from deepagents.profiles._openrouter import (
1941
+ check_openrouter_version, # noqa: PLC2701
1942
+ )
1941
1943
 
1942
1944
  check_openrouter_version()
1943
1945
  _apply_openrouter_defaults(result)
@@ -6,8 +6,11 @@ from deepagents_cli.deploy.commands import (
6
6
  execute_init_command,
7
7
  setup_deploy_parsers,
8
8
  )
9
+ from deepagents_cli.deploy.config import SandboxProvider, SandboxScope
9
10
 
10
11
  __all__ = [
12
+ "SandboxProvider",
13
+ "SandboxScope",
11
14
  "execute_deploy_command",
12
15
  "execute_dev_command",
13
16
  "execute_init_command",
@@ -3,14 +3,22 @@
3
3
  Reads the canonical project layout:
4
4
 
5
5
  ```txt
6
- src/
7
- AGENTS.md # required — system prompt + seeded memory
8
- skills/ # optionalauto-seeded into skills namespace
9
- mcp.json # optional — HTTP/SSE MCP servers
10
- deepagents.toml
6
+ <project>/
7
+ deepagents.toml # required — agent + sandbox config
8
+ AGENTS.md # requiredsystem prompt + seeded memory
9
+ .env # optional — environment variables
10
+ mcp.json # optional — HTTP/SSE MCP servers
11
+ skills/ # optional — auto-seeded into skills namespace
12
+ user/ # optional — per-user writable memory
13
+ AGENTS.md # optional — seeded as empty if not provided
11
14
  ```
12
15
 
13
16
  ...and writes everything `langgraph deploy` needs to a build directory.
17
+
18
+ AGENTS.md and skills are read-only at runtime. When a ``user/``
19
+ directory is present, a per-user ``AGENTS.md`` is seeded (from
20
+ ``user/AGENTS.md`` if provided, otherwise empty) and is writable
21
+ at runtime.
14
22
  """
15
23
 
16
24
  from __future__ import annotations
@@ -24,6 +32,7 @@ from deepagents_cli.deploy.config import (
24
32
  AGENTS_MD_FILENAME,
25
33
  MCP_FILENAME,
26
34
  SKILLS_DIRNAME,
35
+ USER_DIRNAME,
27
36
  DeployConfig,
28
37
  )
29
38
  from deepagents_cli.deploy.templates import (
@@ -35,13 +44,22 @@ from deepagents_cli.deploy.templates import (
35
44
 
36
45
  logger = logging.getLogger(__name__)
37
46
 
38
- _MODEL_PROVIDER_DEPS = {
47
+ _MODEL_PROVIDER_DEPS: dict[str, str] = {
39
48
  "anthropic": "langchain-anthropic",
40
- "openai": "langchain-openai",
49
+ "azure_openai": "langchain-openai",
50
+ "baseten": "langchain-baseten",
51
+ "cohere": "langchain-cohere",
52
+ "deepseek": "langchain-deepseek",
53
+ "fireworks": "langchain-fireworks",
41
54
  "google_genai": "langchain-google-genai",
42
55
  "google_vertexai": "langchain-google-vertexai",
43
56
  "groq": "langchain-groq",
44
57
  "mistralai": "langchain-mistralai",
58
+ "nvidia": "langchain-nvidia-ai-endpoints",
59
+ "openai": "langchain-openai",
60
+ "openrouter": "langchain-openrouter",
61
+ "perplexity": "langchain-perplexity",
62
+ "xai": "langchain-xai",
45
63
  }
46
64
  """Dependencies inferred from a provider: prefix on the model string."""
47
65
 
@@ -65,9 +83,10 @@ def bundle(
65
83
  encoding="utf-8",
66
84
  )
67
85
  logger.info(
68
- "Wrote _seed.json (memories: %d, skills: %d)",
86
+ "Wrote _seed.json (memories: %d, skills: %d, user_memories: %d)",
69
87
  len(seed["memories"]),
70
88
  len(seed["skills"]),
89
+ len(seed.get("user_memories", {})),
71
90
  )
72
91
 
73
92
  # 3. Copy mcp.json if present.
@@ -76,8 +95,8 @@ def bundle(
76
95
  shutil.copy2(project_root / MCP_FILENAME, build_dir / "_mcp.json")
77
96
  logger.info("Copied %s → _mcp.json", MCP_FILENAME)
78
97
 
79
- # 3b. Copy .env from the project root if present (i.e. alongside
80
- # deepagents.toml inside ``src/``). The bundler skips .env when
98
+ # 3b. Copy .env from the project root if present (alongside
99
+ # deepagents.toml). The bundler skips .env when
81
100
  # building the seed payload so secrets never land in _seed.json.
82
101
  env_src = project_root / ".env"
83
102
  env_present = env_src.is_file()
@@ -86,8 +105,13 @@ def bundle(
86
105
  logger.info("Copied %s → .env", env_src)
87
106
 
88
107
  # 4. Render deploy_graph.py.
108
+ has_user_memories = (project_root / USER_DIRNAME).is_dir()
89
109
  (build_dir / "deploy_graph.py").write_text(
90
- _render_deploy_graph(config, system_prompt, mcp_present=mcp_present),
110
+ _render_deploy_graph(
111
+ config,
112
+ mcp_present=mcp_present,
113
+ has_user_memories=has_user_memories,
114
+ ),
91
115
  encoding="utf-8",
92
116
  )
93
117
  logger.info("Generated deploy_graph.py")
@@ -111,31 +135,25 @@ def _build_seed(
111
135
  config: DeployConfig, # noqa: ARG001
112
136
  project_root: Path,
113
137
  system_prompt: str,
114
- ) -> dict[str, dict[str, str]]:
138
+ ) -> dict:
115
139
  """Build the `_seed.json` payload.
116
140
 
117
- Layout:
118
-
119
- ```txt
120
- {
121
- "memories": { "AGENTS.md": "..." },
122
- "skills": { "<skill>/SKILL.md": "...", ... }
123
- }
124
- ```
141
+ Layout::
125
142
 
126
- `memories` always contains `AGENTS.md` — the agent reads it at runtime
127
- via `/memories/AGENTS.md`. Writes and edits to that path are blocked
128
- by `ReadOnlyStoreBackend` in the generated graph.
143
+ {
144
+ "memories": { "/AGENTS.md": "..." },
145
+ "skills": { "/<skill>/SKILL.md": "...", ... },
146
+ "user_memories": { "/AGENTS.md": "..." }
147
+ }
129
148
 
130
- `skills` walks `src/skills/` if present. Keys are paths relative to the
131
- skills dir; the runtime namespace handles the scoping.
149
+ ``memories`` and ``skills`` are read-only at runtime.
150
+ ``user_memories`` contains a single writable ``AGENTS.md`` mounted at
151
+ ``/memories/user/``, namespaced per user_id. If the project has a
152
+ ``user/`` directory (even if empty), an ``AGENTS.md`` is always seeded.
132
153
  """
133
- # Keys must match what CompositeBackend passes to the mounted
134
- # StoreBackend after stripping the route prefix: for a read of
135
- # /memories/AGENTS.md it calls store.read("/AGENTS.md").
136
- # Seed with the same leading-slash convention.
137
154
  memories: dict[str, str] = {f"/{AGENTS_MD_FILENAME}": system_prompt}
138
155
  skills: dict[str, str] = {}
156
+ user_memories: dict[str, str] = {}
139
157
 
140
158
  skills_dir = project_root / SKILLS_DIRNAME
141
159
  if skills_dir.is_dir():
@@ -144,14 +162,28 @@ def _build_seed(
144
162
  rel = f.relative_to(skills_dir).as_posix()
145
163
  skills[f"/{rel}"] = f.read_text(encoding="utf-8")
146
164
 
147
- return {"memories": memories, "skills": skills}
165
+ user_dir = project_root / USER_DIRNAME
166
+ if user_dir.is_dir():
167
+ user_agents_md = user_dir / AGENTS_MD_FILENAME
168
+ content = (
169
+ user_agents_md.read_text(encoding="utf-8")
170
+ if user_agents_md.is_file()
171
+ else ""
172
+ )
173
+ user_memories[f"/{AGENTS_MD_FILENAME}"] = content
174
+
175
+ return {
176
+ "memories": memories,
177
+ "skills": skills,
178
+ "user_memories": user_memories,
179
+ }
148
180
 
149
181
 
150
182
  def _render_deploy_graph(
151
183
  config: DeployConfig,
152
- system_prompt: str,
153
184
  *,
154
185
  mcp_present: bool,
186
+ has_user_memories: bool = False,
155
187
  ) -> str:
156
188
  """Render the generated `deploy_graph.py`."""
157
189
  provider = config.sandbox.provider
@@ -169,7 +201,6 @@ def _render_deploy_graph(
169
201
 
170
202
  return DEPLOY_GRAPH_TEMPLATE.format(
171
203
  model=config.agent.model,
172
- system_prompt=system_prompt,
173
204
  sandbox_template=config.sandbox.template,
174
205
  sandbox_image=config.sandbox.image,
175
206
  sandbox_scope=config.sandbox.scope,
@@ -177,6 +208,7 @@ def _render_deploy_graph(
177
208
  mcp_tools_block=mcp_tools_block,
178
209
  mcp_tools_load_call=mcp_tools_load_call,
179
210
  default_assistant_id=config.agent.name,
211
+ has_user_memories=has_user_memories,
180
212
  )
181
213
 
182
214
 
@@ -231,8 +263,12 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
231
263
  if seed_path.exists():
232
264
  try:
233
265
  seed = json.loads(seed_path.read_text(encoding="utf-8"))
234
- except Exception:
235
- pass
266
+ except (json.JSONDecodeError, OSError) as exc:
267
+ logger.warning(
268
+ "Failed to parse %s; summary may be incomplete: %s",
269
+ seed_path,
270
+ exc,
271
+ )
236
272
 
237
273
  print(f"\n Agent: {config.agent.name}")
238
274
  print(f" Model: {config.agent.model}")
@@ -243,6 +279,12 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
243
279
  for f in memory_files:
244
280
  print(f" {f}")
245
281
 
282
+ user_memory_files = sorted(seed.get("user_memories", {}).keys())
283
+ if user_memory_files:
284
+ print(f"\n User memory seed ({len(user_memory_files)} file(s)):")
285
+ for f in user_memory_files:
286
+ print(f" {f}")
287
+
246
288
  skills_files = sorted(seed.get("skills", {}).keys())
247
289
  if skills_files:
248
290
  print(f"\n Skills seed ({len(skills_files)} file(s)):")
@@ -1,11 +1,6 @@
1
- """CLI commands for `deepagents deploy`.
1
+ """CLI commands for `deepagents init`, `dev`, and `deploy`.
2
2
 
3
- Registered with the CLI via `setup_deploy_parser` in `main.py`.
4
-
5
- Commands:
6
- - `deepagents deploy` — Bundle and deploy to LangGraph Platform
7
- - `deepagents deploy --dry-run` — Show what would be generated
8
- - `deepagents init [NAME]` — Scaffold a new deploy project folder
3
+ Registered with the CLI via `setup_deploy_parsers` in `main.py`.
9
4
  """
10
5
 
11
6
  from __future__ import annotations
@@ -70,7 +65,7 @@ def setup_deploy_parsers(
70
65
  "--config",
71
66
  type=str,
72
67
  default=None,
73
- help="Path to deepagents.toml (default: auto-discovered from cwd upward)",
68
+ help="Path to deepagents.toml (default: auto-discovered from cwd)",
74
69
  )
75
70
  dev_parser.add_argument(
76
71
  "--port",
@@ -100,7 +95,7 @@ def setup_deploy_parsers(
100
95
  "--config",
101
96
  type=str,
102
97
  default=None,
103
- help="Path to deepagents.toml (default: auto-discovered from cwd upward)",
98
+ help="Path to deepagents.toml (default: auto-discovered from cwd)",
104
99
  )
105
100
  deploy_parser.add_argument(
106
101
  "--dry-run",
@@ -197,14 +192,16 @@ def _init_project(*, name: str, force: bool = False) -> None:
197
192
  ]
198
193
 
199
194
  for filename, content in files:
200
- (project_dir / filename).write_text(content)
195
+ (project_dir / filename).write_text(content, encoding="utf-8")
201
196
 
202
197
  # Create skills/ directory with a starter skill.
203
198
  skills_dir = project_dir / SKILLS_DIRNAME
204
199
  skills_dir.mkdir(exist_ok=True)
205
200
  starter_skill_dir = skills_dir / STARTER_SKILL_NAME
206
201
  starter_skill_dir.mkdir(exist_ok=True)
207
- (starter_skill_dir / "SKILL.md").write_text(generate_starter_skill_md())
202
+ (starter_skill_dir / "SKILL.md").write_text(
203
+ generate_starter_skill_md(), encoding="utf-8"
204
+ )
208
205
 
209
206
  print(f"Created {name}/ with:")
210
207
  for filename, _ in files:
@@ -227,6 +224,7 @@ def _deploy(
227
224
  config_path: Path to config file, or `None` for default.
228
225
  dry_run: If `True`, generate artifacts but don't deploy.
229
226
  """
227
+ from deepagents_cli.config import _load_dotenv
230
228
  from deepagents_cli.deploy.bundler import bundle, print_bundle_summary
231
229
  from deepagents_cli.deploy.config import (
232
230
  DEFAULT_CONFIG_FILENAME,
@@ -242,6 +240,11 @@ def _deploy(
242
240
  cfg_path = discovered or Path.cwd() / DEFAULT_CONFIG_FILENAME
243
241
 
244
242
  project_root = cfg_path.parent
243
+ # Ensure the project .env is loaded into os.environ before validation.
244
+ # The main CLI bootstrap loads .env lazily (on first `settings` access),
245
+ # but deploy/dev commands may never touch `settings`, so the project
246
+ # .env would be missing when _validate_model_credentials checks os.environ.
247
+ _load_dotenv(start_path=project_root)
245
248
 
246
249
  # Load and validate config
247
250
  try:
@@ -262,10 +265,7 @@ def _deploy(
262
265
  raise SystemExit(1)
263
266
 
264
267
  # Bundle
265
- if dry_run:
266
- build_dir = Path(tempfile.mkdtemp(prefix="deepagents-deploy-"))
267
- else:
268
- build_dir = Path(tempfile.mkdtemp(prefix="deepagents-deploy-"))
268
+ build_dir = Path(tempfile.mkdtemp(prefix="deepagents-deploy-"))
269
269
 
270
270
  try:
271
271
  bundle(config, project_root, build_dir)
@@ -276,14 +276,13 @@ def _deploy(
276
276
  print(f"Inspect the build directory: {build_dir}")
277
277
  return
278
278
 
279
- # Deploy via langgraph CLI
279
+ # Deploy via langgraph CLI.
280
280
  _run_langgraph_deploy(build_dir, name=config.agent.name)
281
+ finally:
282
+ if not dry_run:
283
+ import shutil
281
284
 
282
- except Exception:
283
- if dry_run:
284
- # Keep build dir for inspection on dry run
285
- raise
286
- raise
285
+ shutil.rmtree(build_dir, ignore_errors=True)
287
286
 
288
287
 
289
288
  def _dev(
@@ -298,7 +297,7 @@ def _dev(
298
297
  served locally instead of pushed to LangGraph Platform. Hot-reloading
299
298
  is provided by `langgraph dev` itself watching the build directory;
300
299
  edits to the source project (`deepagents.toml`, skills, `AGENTS.md`)
301
- require re-running `deepagents deploy dev` to re-bundle.
300
+ require re-running `deepagents dev` to re-bundle.
302
301
 
303
302
  Args:
304
303
  config_path: Path to `deepagents.toml`, or `None` for default.
@@ -309,6 +308,7 @@ def _dev(
309
308
  """
310
309
  import shutil
311
310
 
311
+ from deepagents_cli.config import _load_dotenv
312
312
  from deepagents_cli.deploy.bundler import bundle, print_bundle_summary
313
313
  from deepagents_cli.deploy.config import (
314
314
  DEFAULT_CONFIG_FILENAME,
@@ -322,12 +322,17 @@ def _dev(
322
322
  discovered = find_config()
323
323
  cfg_path = discovered or Path.cwd() / DEFAULT_CONFIG_FILENAME
324
324
  project_root = cfg_path.parent
325
+ # Ensure the project .env is loaded before validation (see _deploy).
326
+ _load_dotenv(start_path=project_root)
325
327
 
326
328
  try:
327
329
  config = load_config(cfg_path)
328
330
  except FileNotFoundError:
329
331
  print(f"Error: Config file not found: {cfg_path}")
330
332
  raise SystemExit(1) from None
333
+ except ValueError as e:
334
+ print(f"Error: Invalid config: {e}")
335
+ raise SystemExit(1) from None
331
336
 
332
337
  errors = config.validate(project_root)
333
338
  if errors:
@@ -337,35 +342,43 @@ def _dev(
337
342
  raise SystemExit(1)
338
343
 
339
344
  build_dir = Path(tempfile.mkdtemp(prefix="deepagents-dev-"))
340
- bundle(config, project_root, build_dir)
341
- print_bundle_summary(config, build_dir)
342
-
343
- if shutil.which("langgraph") is None:
344
- print(
345
- "Error: `langgraph` CLI not found. Install it with:\n"
346
- " pip install 'langgraph-cli[inmem]'"
347
- )
348
- raise SystemExit(1)
345
+ try:
346
+ bundle(config, project_root, build_dir)
347
+ print_bundle_summary(config, build_dir)
349
348
 
350
- cmd = [
351
- "langgraph",
352
- "dev",
353
- "--no-browser",
354
- "--port",
355
- str(port),
356
- ]
357
- if allow_blocking:
358
- cmd.append("--allow-blocking")
349
+ if shutil.which("langgraph") is None:
350
+ print(
351
+ "Error: `langgraph` CLI not found. Install it with:\n"
352
+ " pip install 'langgraph-cli[inmem]'"
353
+ )
354
+ raise SystemExit(1)
359
355
 
360
- print(f"\nStarting langgraph dev on http://localhost:{port}")
361
- print(f"Build directory: {build_dir}")
362
- print(f"Running: {' '.join(cmd)}\n")
356
+ cmd = [
357
+ "langgraph",
358
+ "dev",
359
+ "--no-browser",
360
+ "--port",
361
+ str(port),
362
+ ]
363
+ if allow_blocking:
364
+ cmd.append("--allow-blocking")
365
+
366
+ print(f"\nStarting langgraph dev on http://localhost:{port}")
367
+ print(f"Build directory: {build_dir}")
368
+ print(f"Running: {' '.join(cmd)}\n")
369
+
370
+ # Pass through stdout/stderr so the user sees dev server logs live.
371
+ try:
372
+ result = subprocess.run(cmd, cwd=str(build_dir), check=False)
373
+ except KeyboardInterrupt:
374
+ print("\nShutting down.")
375
+ return
363
376
 
364
- # Pass through stdout/stderr so the user sees the dev server logs live.
365
- try:
366
- subprocess.run(cmd, cwd=str(build_dir), check=False)
367
- except KeyboardInterrupt:
368
- print("\nShutting down.")
377
+ if result.returncode != 0:
378
+ print(f"\nDev server exited with error (exit code {result.returncode}).")
379
+ raise SystemExit(result.returncode)
380
+ finally:
381
+ shutil.rmtree(build_dir, ignore_errors=True)
369
382
 
370
383
 
371
384
  def _run_langgraph_deploy(build_dir: Path, *, name: str) -> None: