deepagents-cli 0.0.37__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 (199) hide show
  1. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/CHANGELOG.md +30 -0
  2. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/PKG-INFO +2 -2
  3. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_version.py +1 -1
  4. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/app.py +63 -11
  5. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/command_registry.py +50 -11
  6. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/deploy/bundler.py +160 -31
  7. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/deploy/commands.py +4 -1
  8. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/deploy/config.py +142 -1
  9. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/deploy/templates.py +251 -41
  10. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/main.py +60 -12
  11. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/model_config.py +10 -1
  12. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/ui.py +3 -0
  13. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/update_check.py +76 -17
  14. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/autocomplete.py +16 -9
  15. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/chat_input.py +207 -5
  16. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/message_store.py +34 -10
  17. deepagents_cli-0.0.39/examples/deploy-content-writer/.env.example +2 -0
  18. deepagents_cli-0.0.39/examples/deploy-content-writer/skills/blog-post/SKILL.md +15 -0
  19. deepagents_cli-0.0.39/examples/deploy-content-writer/skills/social-media/SKILL.md +15 -0
  20. deepagents_cli-0.0.39/examples/deploy-content-writer/user/context.md +15 -0
  21. deepagents_cli-0.0.39/examples/deploy-content-writer/user/preferences.md +11 -0
  22. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/pyproject.toml +2 -2
  23. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/test_compact_resume.py +6 -11
  24. deepagents_cli-0.0.39/tests/unit_tests/deploy/test_bundler.py +541 -0
  25. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/test_config.py +148 -1
  26. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_app.py +166 -0
  27. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_args.py +16 -0
  28. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_autocomplete.py +36 -8
  29. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_chat_input.py +230 -0
  30. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_command_registry.py +14 -9
  31. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_message_store.py +71 -0
  32. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_offload.py +2 -2
  33. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_reload.py +1 -1
  34. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_skill_invocation.py +12 -11
  35. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_update_check.py +228 -0
  36. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/uv.lock +100 -100
  37. deepagents_cli-0.0.37/tests/unit_tests/deploy/test_bundler.py +0 -245
  38. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/.gitignore +0 -0
  39. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/DEV.md +0 -0
  40. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/Makefile +0 -0
  41. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/README.md +0 -0
  42. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/THREAT_MODEL.md +0 -0
  43. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/__init__.py +0 -0
  44. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/__main__.py +0 -0
  45. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_ask_user_types.py +0 -0
  46. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_cli_context.py +0 -0
  47. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_debug.py +0 -0
  48. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_env_vars.py +0 -0
  49. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_server_config.py +0 -0
  50. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_session_stats.py +0 -0
  51. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/_testing_models.py +0 -0
  52. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/agent.py +0 -0
  53. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/app.tcss +0 -0
  54. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/ask_user.py +0 -0
  55. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/__init__.py +0 -0
  56. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
  57. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
  58. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  59. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  60. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/clipboard.py +0 -0
  61. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/config.py +0 -0
  62. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/configurable_model.py +0 -0
  63. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/default_agent_prompt.md +0 -0
  64. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/deploy/__init__.py +0 -0
  65. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/editor.py +0 -0
  66. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/file_ops.py +0 -0
  67. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/formatting.py +0 -0
  68. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/hooks.py +0 -0
  69. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/input.py +0 -0
  70. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/integrations/__init__.py +0 -0
  71. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/integrations/sandbox_factory.py +0 -0
  72. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/integrations/sandbox_provider.py +0 -0
  73. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/local_context.py +0 -0
  74. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/mcp_tools.py +0 -0
  75. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/mcp_trust.py +0 -0
  76. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/media_utils.py +0 -0
  77. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/non_interactive.py +0 -0
  78. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/offload.py +0 -0
  79. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/output.py +0 -0
  80. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/project_utils.py +0 -0
  81. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/py.typed +0 -0
  82. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/remote_client.py +0 -0
  83. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/server.py +0 -0
  84. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/server_graph.py +0 -0
  85. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/server_manager.py +0 -0
  86. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/sessions.py +0 -0
  87. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/skills/__init__.py +0 -0
  88. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/skills/commands.py +0 -0
  89. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/skills/invocation.py +0 -0
  90. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/skills/load.py +0 -0
  91. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/subagents.py +0 -0
  92. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/system_prompt.md +0 -0
  93. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/textual_adapter.py +0 -0
  94. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/theme.py +0 -0
  95. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/token_state.py +0 -0
  96. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/tool_display.py +0 -0
  97. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/tools.py +0 -0
  98. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/unicode_security.py +0 -0
  99. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/__init__.py +0 -0
  100. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/_links.py +0 -0
  101. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/approval.py +0 -0
  102. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/ask_user.py +0 -0
  103. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/diff.py +0 -0
  104. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/history.py +0 -0
  105. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/loading.py +0 -0
  106. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/mcp_viewer.py +0 -0
  107. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/messages.py +0 -0
  108. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/model_selector.py +0 -0
  109. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/notification_settings.py +0 -0
  110. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/status.py +0 -0
  111. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/theme_selector.py +0 -0
  112. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/thread_selector.py +0 -0
  113. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/tool_renderers.py +0 -0
  114. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/tool_widgets.py +0 -0
  115. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/deepagents_cli/widgets/welcome.py +0 -0
  116. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/arxiv-search/SKILL.md +0 -0
  117. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  118. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/langgraph-docs/SKILL.md +0 -0
  119. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/skill-creator/SKILL.md +0 -0
  120. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  121. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  122. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/examples/skills/web-research/SKILL.md +0 -0
  123. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/images/cli.png +0 -0
  124. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/scripts/check_imports.py +0 -0
  125. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/scripts/debug_server.sh +0 -0
  126. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/scripts/install.sh +0 -0
  127. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/README.md +0 -0
  128. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/__init__.py +0 -0
  129. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/__init__.py +0 -0
  130. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  131. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  132. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/conftest.py +0 -0
  133. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/test_acp_mode.py +0 -0
  134. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/test_sandbox_factory.py +0 -0
  135. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/integration_tests/test_sandbox_operations.py +0 -0
  136. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/__init__.py +0 -0
  137. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/conftest.py +0 -0
  138. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/__init__.py +0 -0
  139. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/deploy/test_commands.py +0 -0
  140. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/skills/__init__.py +0 -0
  141. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_commands.py +0 -0
  142. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_load.py +0 -0
  143. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/skills/test_skills_json.py +0 -0
  144. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_agent.py +0 -0
  145. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_agent_friendly.py +0 -0
  146. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_approval.py +0 -0
  147. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_ask_user.py +0 -0
  148. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  149. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_charset.py +0 -0
  150. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_compact_tool.py +0 -0
  151. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_config.py +0 -0
  152. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_configurable_model.py +0 -0
  153. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_debug.py +0 -0
  154. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_editor.py +0 -0
  155. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_end_to_end.py +0 -0
  156. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_env_vars.py +0 -0
  157. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_exception_handling.py +0 -0
  158. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_file_ops.py +0 -0
  159. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_history.py +0 -0
  160. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_hooks.py +0 -0
  161. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_imports.py +0 -0
  162. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_input_parsing.py +0 -0
  163. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_links.py +0 -0
  164. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_loading.py +0 -0
  165. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_local_context.py +0 -0
  166. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_main.py +0 -0
  167. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_main_acp_mode.py +0 -0
  168. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_main_args.py +0 -0
  169. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_tools.py +0 -0
  170. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_trust.py +0 -0
  171. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_mcp_viewer.py +0 -0
  172. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_media_utils.py +0 -0
  173. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_messages.py +0 -0
  174. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_config.py +0 -0
  175. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_selector.py +0 -0
  176. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_model_switch.py +0 -0
  177. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_non_interactive.py +0 -0
  178. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_output.py +0 -0
  179. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_remote_client.py +0 -0
  180. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_sandbox_factory.py +0 -0
  181. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_server.py +0 -0
  182. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_config.py +0 -0
  183. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_graph.py +0 -0
  184. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_helpers.py +0 -0
  185. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_server_manager.py +0 -0
  186. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_sessions.py +0 -0
  187. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_shell_allow_list.py +0 -0
  188. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_status.py +0 -0
  189. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_subagents.py +0 -0
  190. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_textual_adapter.py +0 -0
  191. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_theme.py +0 -0
  192. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_thread_selector.py +0 -0
  193. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_token_tracker.py +0 -0
  194. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_ui.py +0 -0
  195. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_unicode_security.py +0 -0
  196. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_version.py +0 -0
  197. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/test_welcome.py +0 -0
  198. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/tools/__init__.py +0 -0
  199. {deepagents_cli-0.0.37 → deepagents_cli-0.0.39}/tests/unit_tests/tools/test_fetch_url.py +0 -0
@@ -1,5 +1,35 @@
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
+
16
+ ## [0.0.38](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.37...deepagents-cli==0.0.38) (2026-04-15)
17
+
18
+
19
+ ### Features
20
+
21
+ * **cli:** user scoped memory ([#2708](https://github.com/langchain-ai/deepagents/issues/2708)) ([23bfca6](https://github.com/langchain-ai/deepagents/commit/23bfca6e46e6f3e4fba6657d858ddd5a0b06626f))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * **deepagents:** remove old integration tests ([#2728](https://github.com/langchain-ai/deepagents/issues/2728)) ([6653197](https://github.com/langchain-ai/deepagents/commit/6653197b6cbec6dd1ca23d9f90bc1439ca26e6e5))
27
+
28
+
29
+ ### Performance Improvements
30
+
31
+ * **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))
32
+
3
33
  ## [0.0.37](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.36...deepagents-cli==0.0.37) (2026-04-10)
4
34
 
5
35
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.0.37
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/
@@ -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.2
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.37" # 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."""
@@ -1505,11 +1515,15 @@ class DeepAgentsApp(App):
1505
1515
 
1506
1516
  try:
1507
1517
  from deepagents_cli._version import __version__ as cli_version
1518
+ from deepagents_cli.config import _is_editable_install
1519
+
1520
+ if await asyncio.to_thread(_is_editable_install):
1521
+ heading = f"Now running v{cli_version}"
1522
+ else:
1523
+ heading = f"Updated to v{cli_version}"
1508
1524
 
1509
1525
  await self._mount_message(
1510
- AppMessage(
1511
- f"Updated to v{cli_version}\nSee what's new: {CHANGELOG_URL}"
1512
- )
1526
+ AppMessage(f"{heading}\nSee what's new: {CHANGELOG_URL}")
1513
1527
  )
1514
1528
  except Exception:
1515
1529
  logger.debug("What's new banner display failed", exc_info=True)
@@ -2759,6 +2773,15 @@ class DeepAgentsApp(App):
2759
2773
  elif cmd == "/remember" or cmd.startswith("/remember "):
2760
2774
  # Convenience alias for /skill:remember — shorter and discoverable
2761
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
2762
2785
  args = command.strip()[len("/remember") :].strip()
2763
2786
  rewritten = f"/skill:remember {args}" if args else "/skill:remember"
2764
2787
  await self._handle_skill_command(rewritten)
@@ -3039,6 +3062,35 @@ class DeepAgentsApp(App):
3039
3062
  skill_name, args = parse_skill_command(command)
3040
3063
  await self._invoke_skill(skill_name, args, command=command)
3041
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
+
3042
3094
  async def _get_conversation_token_count(self) -> int | None:
3043
3095
  """Return the approximate conversation-only token count.
3044
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
  ]
@@ -9,9 +9,16 @@ Reads the canonical project layout:
9
9
  .env # optional — environment variables
10
10
  mcp.json # optional — HTTP/SSE MCP servers
11
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
12
14
  ```
13
15
 
14
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.
15
22
  """
16
23
 
17
24
  from __future__ import annotations
@@ -20,18 +27,23 @@ import json
20
27
  import logging
21
28
  import shutil
22
29
  from pathlib import Path
30
+ from typing import Any
23
31
 
24
32
  from deepagents_cli.deploy.config import (
25
33
  AGENTS_MD_FILENAME,
26
34
  MCP_FILENAME,
27
35
  SKILLS_DIRNAME,
36
+ USER_DIRNAME,
28
37
  DeployConfig,
38
+ SubAgentProject,
39
+ load_subagents,
29
40
  )
30
41
  from deepagents_cli.deploy.templates import (
31
42
  DEPLOY_GRAPH_TEMPLATE,
32
43
  MCP_TOOLS_TEMPLATE,
33
44
  PYPROJECT_TEMPLATE,
34
45
  SANDBOX_BLOCKS,
46
+ SYNC_SUBAGENTS_TEMPLATE,
35
47
  )
36
48
 
37
49
  logger = logging.getLogger(__name__)
@@ -69,15 +81,16 @@ def bundle(
69
81
  system_prompt = agents_md_path.read_text(encoding="utf-8")
70
82
 
71
83
  # 2. Build and write the seed payload: memory (AGENTS.md) + skills/.
72
- seed = _build_seed(config, project_root, system_prompt)
84
+ seed = _build_seed(project_root, system_prompt)
73
85
  (build_dir / "_seed.json").write_text(
74
86
  json.dumps(seed, indent=2, ensure_ascii=False),
75
87
  encoding="utf-8",
76
88
  )
77
89
  logger.info(
78
- "Wrote _seed.json (memories: %d, skills: %d)",
90
+ "Wrote _seed.json (memories: %d, skills: %d, user_memories: %d)",
79
91
  len(seed["memories"]),
80
92
  len(seed["skills"]),
93
+ len(seed.get("user_memories", {})),
81
94
  )
82
95
 
83
96
  # 3. Copy mcp.json if present.
@@ -95,58 +108,110 @@ def bundle(
95
108
  shutil.copy2(env_src, build_dir / ".env")
96
109
  logger.info("Copied %s → .env", env_src)
97
110
 
98
- # 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.
115
+ has_user_memories = (project_root / USER_DIRNAME).is_dir()
116
+ has_sync_subagents = bool(sync_subagents)
99
117
  (build_dir / "deploy_graph.py").write_text(
100
- _render_deploy_graph(config, mcp_present=mcp_present),
118
+ _render_deploy_graph(
119
+ config,
120
+ mcp_present=mcp_present,
121
+ has_user_memories=has_user_memories,
122
+ has_sync_subagents=has_sync_subagents,
123
+ ),
101
124
  encoding="utf-8",
102
125
  )
103
126
  logger.info("Generated deploy_graph.py")
104
127
 
105
- # 5. Render langgraph.json.
128
+ # 6. Render langgraph.json.
106
129
  (build_dir / "langgraph.json").write_text(
107
130
  _render_langgraph_json(env_present=env_present),
108
131
  encoding="utf-8",
109
132
  )
110
133
 
111
- # 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
+
112
144
  (build_dir / "pyproject.toml").write_text(
113
- _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
+ ),
114
151
  encoding="utf-8",
115
152
  )
116
153
 
117
154
  return build_dir
118
155
 
119
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
+
120
193
  def _build_seed(
121
- config: DeployConfig, # noqa: ARG001
122
194
  project_root: Path,
123
195
  system_prompt: str,
124
- ) -> dict[str, dict[str, str]]:
196
+ ) -> dict:
125
197
  """Build the `_seed.json` payload.
126
198
 
127
- Layout:
199
+ Layout::
128
200
 
129
- ```txt
130
- {
131
- "memories": { "/AGENTS.md": "..." },
132
- "skills": { "/<skill>/SKILL.md": "...", ... }
133
- }
134
- ```
135
-
136
- `memories` always contains `/AGENTS.md` — the middleware loads it at
137
- startup via `/memories/AGENTS.md`. Agent reads of `/memories/` and
138
- `/skills/` are denied by `FilesystemPermission` rules.
201
+ {
202
+ "memories": { "/AGENTS.md": "..." },
203
+ "skills": { "/<skill>/SKILL.md": "...", ... },
204
+ "user_memories": { "/AGENTS.md": "..." }
205
+ }
139
206
 
140
- `skills` walks `skills/` if present. Keys are paths relative to the
141
- skills dir with a leading slash; the runtime namespace handles the
142
- scoping.
207
+ ``memories`` and ``skills`` are read-only at runtime.
208
+ ``user_memories`` contains a single writable ``AGENTS.md`` mounted at
209
+ ``/memories/user/``, namespaced per user_id. If the project has a
210
+ ``user/`` directory (even if empty), an ``AGENTS.md`` is always seeded.
143
211
  """
144
- # Keys must match what CompositeBackend passes to the mounted
145
- # StoreBackend after stripping the route prefix: for a read of
146
- # /memories/AGENTS.md it calls store.read("/AGENTS.md").
147
- # Seed with the same leading-slash convention.
148
212
  memories: dict[str, str] = {f"/{AGENTS_MD_FILENAME}": system_prompt}
149
213
  skills: dict[str, str] = {}
214
+ user_memories: dict[str, str] = {}
150
215
 
151
216
  skills_dir = project_root / SKILLS_DIRNAME
152
217
  if skills_dir.is_dir():
@@ -155,13 +220,38 @@ def _build_seed(
155
220
  rel = f.relative_to(skills_dir).as_posix()
156
221
  skills[f"/{rel}"] = f.read_text(encoding="utf-8")
157
222
 
158
- return {"memories": memories, "skills": skills}
223
+ user_dir = project_root / USER_DIRNAME
224
+ if user_dir.is_dir():
225
+ user_agents_md = user_dir / AGENTS_MD_FILENAME
226
+ content = (
227
+ user_agents_md.read_text(encoding="utf-8")
228
+ if user_agents_md.is_file()
229
+ else ""
230
+ )
231
+ user_memories[f"/{AGENTS_MD_FILENAME}"] = content
232
+
233
+ seed: dict = {
234
+ "memories": memories,
235
+ "skills": skills,
236
+ "user_memories": user_memories,
237
+ }
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
159
247
 
160
248
 
161
249
  def _render_deploy_graph(
162
250
  config: DeployConfig,
163
251
  *,
164
252
  mcp_present: bool,
253
+ has_user_memories: bool = False,
254
+ has_sync_subagents: bool = False,
165
255
  ) -> str:
166
256
  """Render the generated `deploy_graph.py`."""
167
257
  provider = config.sandbox.provider
@@ -177,6 +267,16 @@ def _render_deploy_graph(
177
267
  mcp_tools_block = ""
178
268
  mcp_tools_load_call = "pass # no MCP servers configured"
179
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
+
180
280
  return DEPLOY_GRAPH_TEMPLATE.format(
181
281
  model=config.agent.model,
182
282
  sandbox_template=config.sandbox.template,
@@ -186,6 +286,9 @@ def _render_deploy_graph(
186
286
  mcp_tools_block=mcp_tools_block,
187
287
  mcp_tools_load_call=mcp_tools_load_call,
188
288
  default_assistant_id=config.agent.name,
289
+ has_user_memories=has_user_memories,
290
+ sync_subagents_block=sync_subagents_block,
291
+ sync_subagents_load_call=sync_subagents_load_call,
189
292
  )
190
293
 
191
294
 
@@ -201,7 +304,13 @@ def _render_langgraph_json(*, env_present: bool) -> str:
201
304
  return json.dumps(data, indent=2) + "\n"
202
305
 
203
306
 
204
- 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:
205
314
  """Render the deployment package's `pyproject.toml`.
206
315
 
207
316
  Deps are inferred — the user never writes them. We add:
@@ -218,7 +327,13 @@ def _render_pyproject(config: DeployConfig, *, mcp_present: bool) -> str:
218
327
  if provider_prefix and provider_prefix in _MODEL_PROVIDER_DEPS:
219
328
  deps.append(_MODEL_PROVIDER_DEPS[provider_prefix])
220
329
 
221
- 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:
222
337
  deps.append("langchain-mcp-adapters")
223
338
 
224
339
  _, partner_pkg = SANDBOX_BLOCKS.get(config.sandbox.provider, (None, None))
@@ -236,7 +351,7 @@ def _render_pyproject(config: DeployConfig, *, mcp_present: bool) -> str:
236
351
  def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
237
352
  """Print a human-readable summary of what was bundled."""
238
353
  seed_path = build_dir / "_seed.json"
239
- seed: dict[str, dict[str, str]] = {"memories": {}, "skills": {}}
354
+ seed: dict[str, Any] = {"memories": {}, "skills": {}}
240
355
  if seed_path.exists():
241
356
  try:
242
357
  seed = json.loads(seed_path.read_text(encoding="utf-8"))
@@ -256,6 +371,12 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
256
371
  for f in memory_files:
257
372
  print(f" {f}")
258
373
 
374
+ user_memory_files = sorted(seed.get("user_memories", {}).keys())
375
+ if user_memory_files:
376
+ print(f"\n User memory seed ({len(user_memory_files)} file(s)):")
377
+ for f in user_memory_files:
378
+ print(f" {f}")
379
+
259
380
  skills_files = sorted(seed.get("skills", {}).keys())
260
381
  if skills_files:
261
382
  print(f"\n Skills seed ({len(skills_files)} file(s)):")
@@ -265,6 +386,14 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
265
386
  if (build_dir / "_mcp.json").exists():
266
387
  print("\n MCP config: _mcp.json")
267
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
+
268
397
  print(f"\n Sandbox: {config.sandbox.provider}")
269
398
  print(f"\n Build directory: {build_dir}")
270
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}).")