deepagents-code 0.1.30__tar.gz → 0.1.31__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 (320) hide show
  1. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/CHANGELOG.md +21 -0
  2. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/Makefile +5 -1
  3. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/PKG-INFO +4 -1
  4. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_build_info.py +1 -1
  5. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_env_vars.py +14 -0
  6. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_version.py +1 -1
  7. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/agent.py +5 -0
  8. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/app.py +223 -77
  9. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/config.py +55 -8
  10. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/config_commands.py +160 -89
  11. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/config_manifest.py +9 -1
  12. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/extras_info.py +5 -4
  13. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/main.py +1 -5
  14. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/model_config.py +29 -0
  15. deepagents_code-0.1.31/deepagents_code/paste_collapse.py +103 -0
  16. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/reasoning_effort.py +36 -13
  17. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/textual_adapter.py +2 -2
  18. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/tool_display.py +10 -1
  19. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/ui.py +5 -4
  20. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/update_check.py +45 -0
  21. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/auth.py +48 -5
  22. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/chat_input.py +195 -26
  23. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/cwd_switch.py +46 -4
  24. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/install_confirm.py +1 -1
  25. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/message_store.py +8 -3
  26. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/messages.py +234 -38
  27. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/model_selector.py +206 -77
  28. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/status.py +55 -7
  29. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/thread_selector.py +7 -4
  30. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/pyproject.toml +4 -2
  31. deepagents_code-0.1.31/tests/unit_tests/smoke_tests/conftest.py +28 -0
  32. deepagents_code-0.1.31/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +537 -0
  33. deepagents_code-0.1.31/tests/unit_tests/smoke_tests/test_system_prompt.py +199 -0
  34. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_agent.py +39 -0
  35. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_app.py +593 -2
  36. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_auth_widgets.py +29 -5
  37. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_autocomplete.py +7 -1
  38. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_chat_input.py +585 -0
  39. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_config.py +330 -0
  40. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_config_manifest.py +145 -3
  41. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_cwd_switch.py +69 -1
  42. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_message_store.py +35 -0
  43. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_messages.py +424 -1
  44. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_model_config.py +19 -1
  45. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_model_selector.py +351 -10
  46. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_model_switch.py +119 -0
  47. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_reasoning_effort.py +27 -5
  48. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_status.py +115 -0
  49. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_thread_selector.py +128 -7
  50. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_update_check.py +152 -0
  51. deepagents_code-0.1.31/tests/unit_tests/widgets/__init__.py +0 -0
  52. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/uv.lock +41 -3
  53. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/.gitignore +0 -0
  54. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/AGENTS.md +0 -0
  55. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/ARCHITECTURE.md +0 -0
  56. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/COMMANDS.md +0 -0
  57. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/DEVELOPMENT.md +0 -0
  58. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/README.md +0 -0
  59. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/THREAT_MODEL.md +0 -0
  60. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/__init__.py +0 -0
  61. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/__main__.py +0 -0
  62. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_ask_user_types.py +0 -0
  63. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_cli_context.py +0 -0
  64. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_constants.py +0 -0
  65. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_debug.py +0 -0
  66. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_git.py +0 -0
  67. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_paths.py +0 -0
  68. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_server_config.py +0 -0
  69. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_session_stats.py +0 -0
  70. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_startup_error.py +0 -0
  71. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_testing_models.py +0 -0
  72. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/_textual_patches.py +0 -0
  73. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/app.tcss +0 -0
  74. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/approval_mode.py +0 -0
  75. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/ask_user.py +0 -0
  76. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/auth_commands.py +0 -0
  77. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/auth_display.py +0 -0
  78. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/auth_store.py +0 -0
  79. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/built_in_skills/__init__.py +0 -0
  80. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  81. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  82. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  83. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  84. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/clipboard.py +0 -0
  85. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/command_registry.py +0 -0
  86. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/configurable_model.py +0 -0
  87. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/default_agent_prompt.md +0 -0
  88. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/doctor.py +0 -0
  89. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/editor.py +0 -0
  90. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/event_bus.py +0 -0
  91. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/file_ops.py +0 -0
  92. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/formatting.py +0 -0
  93. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/goal_rubric.py +0 -0
  94. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/goal_tools.py +0 -0
  95. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/hooks.py +0 -0
  96. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/input.py +0 -0
  97. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/__init__.py +0 -0
  98. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/openai_codex.py +0 -0
  99. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/sandbox_config.py +0 -0
  100. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/sandbox_factory.py +0 -0
  101. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/sandbox_provider.py +0 -0
  102. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/integrations/sandbox_registry.py +0 -0
  103. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/iterm_cursor_guide.py +0 -0
  104. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/local_context.py +0 -0
  105. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/managed_tools.py +0 -0
  106. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_auth.py +0 -0
  107. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_commands.py +0 -0
  108. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_disabled.py +0 -0
  109. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_login_service.py +0 -0
  110. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_oauth_ui.py +0 -0
  111. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_providers/__init__.py +0 -0
  112. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_providers/_registry.py +0 -0
  113. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_providers/base.py +0 -0
  114. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_providers/github.py +0 -0
  115. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_providers/slack.py +0 -0
  116. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_tools.py +0 -0
  117. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/mcp_trust.py +0 -0
  118. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/media_utils.py +0 -0
  119. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/memory_guard.py +0 -0
  120. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/non_interactive.py +0 -0
  121. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/notifications.py +0 -0
  122. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/offload.py +0 -0
  123. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/onboarding.py +0 -0
  124. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/output.py +0 -0
  125. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/project_utils.py +0 -0
  126. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/py.typed +0 -0
  127. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/remote_client.py +0 -0
  128. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/resume_state.py +0 -0
  129. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/server.py +0 -0
  130. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/server_graph.py +0 -0
  131. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/server_manager.py +0 -0
  132. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/sessions.py +0 -0
  133. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/skills/__init__.py +0 -0
  134. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/skills/commands.py +0 -0
  135. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/skills/invocation.py +0 -0
  136. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/skills/load.py +0 -0
  137. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/state_migration.py +0 -0
  138. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/subagents.py +0 -0
  139. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/system_prompt.md +0 -0
  140. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/terminal_capabilities.py +0 -0
  141. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/terminal_escape.py +0 -0
  142. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/theme.py +0 -0
  143. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/tools.py +0 -0
  144. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/tools_commands.py +0 -0
  145. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/unicode_security.py +0 -0
  146. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/__init__.py +0 -0
  147. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/_js_eval_display.py +0 -0
  148. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/_links.py +0 -0
  149. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/agent_selector.py +0 -0
  150. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/approval.py +0 -0
  151. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/ask_user.py +0 -0
  152. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/autocomplete.py +0 -0
  153. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/codex_auth.py +0 -0
  154. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/diff.py +0 -0
  155. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/effort_selector.py +0 -0
  156. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/goal_review.py +0 -0
  157. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/history.py +0 -0
  158. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/launch_init.py +0 -0
  159. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/loading.py +0 -0
  160. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/mcp_login.py +0 -0
  161. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/mcp_reconnect.py +0 -0
  162. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/mcp_viewer.py +0 -0
  163. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/notification_center.py +0 -0
  164. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/notification_detail.py +0 -0
  165. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/notification_settings.py +0 -0
  166. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/restart_prompt.py +0 -0
  167. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/subagent_panel.py +0 -0
  168. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/theme_selector.py +0 -0
  169. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/tool_renderers.py +0 -0
  170. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/tool_widgets.py +0 -0
  171. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/update_available.py +0 -0
  172. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/update_confirm.py +0 -0
  173. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/update_progress.py +0 -0
  174. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/deepagents_code/widgets/welcome.py +0 -0
  175. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/arxiv-search/SKILL.md +0 -0
  176. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  177. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/langgraph-docs/SKILL.md +0 -0
  178. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/skill-creator/SKILL.md +0 -0
  179. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  180. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  181. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/examples/skills/web-research/SKILL.md +0 -0
  182. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/hatch_build.py +0 -0
  183. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/images/tui.png +0 -0
  184. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/scripts/check_imports.py +0 -0
  185. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/scripts/debug_server.sh +0 -0
  186. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/scripts/generate_commands_catalog.py +0 -0
  187. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/scripts/install.sh +0 -0
  188. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/README.md +0 -0
  189. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/__init__.py +0 -0
  190. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/benchmarks/__init__.py +0 -0
  191. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  192. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  193. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/conftest.py +0 -0
  194. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/test_acp_mode.py +0 -0
  195. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/test_auto_approve_remote.py +0 -0
  196. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/test_compact_resume.py +0 -0
  197. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/test_sandbox_factory.py +0 -0
  198. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/integration_tests/test_sandbox_operations.py +0 -0
  199. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/__init__.py +0 -0
  200. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/conftest.py +0 -0
  201. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
  202. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/skills/__init__.py +0 -0
  203. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/skills/test_commands.py +0 -0
  204. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/skills/test_load.py +0 -0
  205. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/skills/test_skills_json.py +0 -0
  206. {deepagents_code-0.1.30/tests/unit_tests/tools → deepagents_code-0.1.31/tests/unit_tests/smoke_tests}/__init__.py +0 -0
  207. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_agent_friendly.py +0 -0
  208. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_agent_selector.py +0 -0
  209. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_approval.py +0 -0
  210. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_approval_mode.py +0 -0
  211. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_args.py +0 -0
  212. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_ask_user.py +0 -0
  213. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  214. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_auth_commands.py +0 -0
  215. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_auth_display.py +0 -0
  216. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_auth_store.py +0 -0
  217. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_charset.py +0 -0
  218. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_clipboard.py +0 -0
  219. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
  220. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_command_registry.py +0 -0
  221. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_compact_tool.py +0 -0
  222. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_configurable_model.py +0 -0
  223. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_cursor_blink.py +0 -0
  224. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_debug.py +0 -0
  225. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_doctor.py +0 -0
  226. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_editor.py +0 -0
  227. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_end_to_end.py +0 -0
  228. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_env_vars.py +0 -0
  229. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_event_bus.py +0 -0
  230. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_exception_handling.py +0 -0
  231. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_extras_info.py +0 -0
  232. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_file_ops.py +0 -0
  233. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_formatting.py +0 -0
  234. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_git.py +0 -0
  235. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_goal_review.py +0 -0
  236. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_goal_rubric.py +0 -0
  237. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_goal_tools.py +0 -0
  238. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_hatch_build.py +0 -0
  239. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_history.py +0 -0
  240. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_hooks.py +0 -0
  241. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_imports.py +0 -0
  242. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_input_parsing.py +0 -0
  243. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_install_command.py +0 -0
  244. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_install_confirm.py +0 -0
  245. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_install_script.py +0 -0
  246. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  247. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_launch_init.py +0 -0
  248. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_links.py +0 -0
  249. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_loading.py +0 -0
  250. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_local_context.py +0 -0
  251. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_main.py +0 -0
  252. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_main_acp_mode.py +0 -0
  253. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_main_args.py +0 -0
  254. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_managed_tools.py +0 -0
  255. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_auth.py +0 -0
  256. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_commands.py +0 -0
  257. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_disabled.py +0 -0
  258. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_login_modal.py +0 -0
  259. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_login_service.py +0 -0
  260. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  261. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_reconnect.py +0 -0
  262. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_tools.py +0 -0
  263. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_trust.py +0 -0
  264. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_mcp_viewer.py +0 -0
  265. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_media_utils.py +0 -0
  266. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_memory_guard.py +0 -0
  267. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_non_interactive.py +0 -0
  268. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_notification_center.py +0 -0
  269. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_notification_detail.py +0 -0
  270. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_notifications.py +0 -0
  271. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_offload.py +0 -0
  272. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_offload_dict_messages.py +0 -0
  273. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_onboarding.py +0 -0
  274. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  275. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_output.py +0 -0
  276. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_paths.py +0 -0
  277. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_reload.py +0 -0
  278. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_remote_client.py +0 -0
  279. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_restart_prompt.py +0 -0
  280. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_resume_state.py +0 -0
  281. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_rubric_cli.py +0 -0
  282. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_sandbox_config.py +0 -0
  283. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_sandbox_factory.py +0 -0
  284. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_sandbox_provider.py +0 -0
  285. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_sandbox_registry.py +0 -0
  286. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_server.py +0 -0
  287. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_server_config.py +0 -0
  288. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_server_graph.py +0 -0
  289. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_server_helpers.py +0 -0
  290. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_server_manager.py +0 -0
  291. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_session_stats.py +0 -0
  292. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_sessions.py +0 -0
  293. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_shell_allow_list.py +0 -0
  294. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_skill_invocation.py +0 -0
  295. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  296. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_state_migration.py +0 -0
  297. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_subagent_panel.py +0 -0
  298. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_subagent_stream.py +0 -0
  299. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_subagents.py +0 -0
  300. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  301. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_terminal_escape.py +0 -0
  302. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  303. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_textual_adapter.py +0 -0
  304. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_textual_patches.py +0 -0
  305. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_theme.py +0 -0
  306. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_tool_display.py +0 -0
  307. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_tool_renderers.py +0 -0
  308. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_tools_commands.py +0 -0
  309. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_tracing_replicas.py +0 -0
  310. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_ui.py +0 -0
  311. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_unicode_security.py +0 -0
  312. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_update_available.py +0 -0
  313. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_update_confirm.py +0 -0
  314. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_update_progress.py +0 -0
  315. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_version.py +0 -0
  316. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/test_welcome.py +0 -0
  317. {deepagents_code-0.1.30/tests/unit_tests/widgets → deepagents_code-0.1.31/tests/unit_tests/tools}/__init__.py +0 -0
  318. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/tools/test_current_thread.py +0 -0
  319. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  320. {deepagents_code-0.1.30 → deepagents_code-0.1.31}/tests/unit_tests/widgets/test_diff.py +0 -0
@@ -2,6 +2,27 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.31](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.30...deepagents-code==0.1.31) (2026-07-03)
6
+
7
+ ### Features
8
+
9
+ * Collapse large pastes into compact placeholders ([#4447](https://github.com/langchain-ai/deepagents/issues/4447)) ([9ae927d](https://github.com/langchain-ai/deepagents/commit/9ae927d73ebf30ba50bbb7ec0c1076a0937e5cb7))
10
+ * Show model name instead of spec in switcher ([#4460](https://github.com/langchain-ai/deepagents/issues/4460)) ([0059620](https://github.com/langchain-ai/deepagents/commit/005962088ad31b16745c399e4ab2e725e97f7858))
11
+ * Offer abort during resume ([#4188](https://github.com/langchain-ai/deepagents/issues/4188)) ([a4c25cd](https://github.com/langchain-ai/deepagents/commit/a4c25cd74de9902fd0ea9440b5dda2d4248bb3d2))
12
+ * Persistent banner when installation is stale ([#4459](https://github.com/langchain-ai/deepagents/issues/4459)) ([b74c185](https://github.com/langchain-ai/deepagents/commit/b74c18591a8ce9a49a5fee43b07e602ca9fbf68a))
13
+ * Show `"Took <duration>"` after `execute` finishes ([#4301](https://github.com/langchain-ai/deepagents/issues/4301)) ([a5240eb](https://github.com/langchain-ai/deepagents/commit/a5240ebe3654e72fa5beb4070224f52f944768c8))
14
+ * Unify `config show`/`list` around effective values ([#4174](https://github.com/langchain-ai/deepagents/issues/4174)) ([ccd9d21](https://github.com/langchain-ai/deepagents/commit/ccd9d216e77855a28b88850beb525f47ce8b686a))
15
+
16
+ ### Bug Fixes
17
+
18
+ * Make execute command expandable in code TUI transcript ([#4428](https://github.com/langchain-ai/deepagents/issues/4428)) ([d999181](https://github.com/langchain-ai/deepagents/commit/d999181e8424498681f1e442c71380bf6b82b0aa))
19
+ * Allow suppressing LangSmith key override warning ([#4436](https://github.com/langchain-ai/deepagents/issues/4436)) ([ddcae5e](https://github.com/langchain-ai/deepagents/commit/ddcae5e0bd9aebc946be1d9fb3f5e35eeb690fa6))
20
+ * Ensure unique message widget IDs on history load ([#4454](https://github.com/langchain-ai/deepagents/issues/4454)) ([de2f7d2](https://github.com/langchain-ai/deepagents/commit/de2f7d2835485df905772e1c96e33d2c239d8e22))
21
+ * Resolve `/threads` header link on mount, not after load ([#4453](https://github.com/langchain-ai/deepagents/issues/4453)) ([4cba728](https://github.com/langchain-ai/deepagents/commit/4cba72893fc4aae5b429d8c573c1a513d97ddf8a))
22
+ * Restore caller's LangSmith API key in shell subprocess env ([#4458](https://github.com/langchain-ai/deepagents/issues/4458)) ([9293b19](https://github.com/langchain-ai/deepagents/commit/9293b190170a872b73d0d94e66479bcc5f7962c7))
23
+ * Route Anthropic effort through output config ([#4446](https://github.com/langchain-ai/deepagents/issues/4446)) ([1e8ed81](https://github.com/langchain-ai/deepagents/commit/1e8ed81940a862dde44f704826b61650336367e0))
24
+ * Show loading state during model switch ([#4209](https://github.com/langchain-ai/deepagents/issues/4209)) ([7cc4e9f](https://github.com/langchain-ai/deepagents/commit/7cc4e9f9bda5a8ae42bb072b82b634ad8c39ade1))
25
+
5
26
  ## [0.1.30](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.29...deepagents-code==0.1.30) (2026-07-02)
6
27
 
7
28
  ### Features
@@ -1,4 +1,4 @@
1
- .PHONY: format lint type typecheck test tests integration_test integration_tests test_watch benchmark bench bench-memory help run lint_package lint_tests check_imports coverage commands-catalog commands-catalog-check check bootstrap
1
+ .PHONY: format lint type typecheck test tests integration_test integration_tests test_watch benchmark bench bench-memory help run lint_package lint_tests check_imports coverage commands-catalog commands-catalog-check check bootstrap update-snapshots
2
2
 
3
3
  .DEFAULT_GOAL := help
4
4
 
@@ -16,8 +16,12 @@ TEST_FILE ?= tests/unit_tests/
16
16
  integration_test integration_tests: TEST_FILE=tests/integration_tests/
17
17
 
18
18
  COV_ARGS ?= --cov=deepagents_code --cov-report=term-missing
19
+ SMOKE_TESTS ?= tests/unit_tests/smoke_tests/
19
20
  PYTEST_EXTRA ?=
20
21
 
22
+ update-snapshots: ## Update smoke test snapshots
23
+ uv run --group test pytest -vvv --disable-socket --allow-unix-socket --update-snapshots $(SMOKE_TESTS)
24
+
21
25
  test: ## Run unit tests
22
26
  test tests:
23
27
  uv run --group test pytest -n auto --benchmark-disable --disable-socket --allow-unix-socket $(PYTEST_EXTRA) $(TEST_FILE) \
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-code
3
- Version: 0.1.30
3
+ Version: 0.1.31
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/
@@ -111,6 +111,9 @@ Provides-Extra: ibm
111
111
  Requires-Dist: langchain-ibm<2.0.0,>=1.1.0; extra == 'ibm'
112
112
  Provides-Extra: litellm
113
113
  Requires-Dist: langchain-litellm<2.0.0,>=0.7.0; extra == 'litellm'
114
+ Provides-Extra: media
115
+ Requires-Dist: av<18.0.0,>=17.0.0; extra == 'media'
116
+ Requires-Dist: pillow<13.0.0,>=12.2.0; extra == 'media'
114
117
  Provides-Extra: mistralai
115
118
  Requires-Dist: langchain-mistralai<2.0.0,>=1.1.5; extra == 'mistralai'
116
119
  Provides-Extra: modal
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "e4709c2"
3
+ BUILD_COMMIT = "0390043"
@@ -225,6 +225,20 @@ Defaults to enabled; set to a falsy value (`0`, `false`, `no`, `off`, or empty)
225
225
  to suppress the success toast while still opening URLs normally.
226
226
  """
227
227
 
228
+ SUPPRESS_ENV_OVERRIDE_WARNING = "DEEPAGENTS_CODE_SUPPRESS_ENV_OVERRIDE_WARNING"
229
+ """Silence the startup warning emitted when a `DEEPAGENTS_CODE_`-prefixed
230
+ LangSmith variable overrides its canonical counterpart (e.g. both
231
+ `LANGSMITH_API_KEY` and `DEEPAGENTS_CODE_LANGSMITH_API_KEY` are set to
232
+ different values).
233
+
234
+ The override is intentional: the prefixed value overwrites the canonical
235
+ variable inside the Deep Agents Code process (so the LangSmith SDK, which
236
+ only reads canonical names, picks it up). The value you exported in your own
237
+ shell is unaffected, since a process cannot change its parent's environment.
238
+ Off by default; set to a truthy value (`1`, `true`, `yes`, `on`) to suppress
239
+ the warning when this coexistence is expected. Parsed by `is_env_truthy`.
240
+ """
241
+
228
242
  THEME = "DEEPAGENTS_CODE_THEME"
229
243
  """Force the CLI to launch with this theme name when set."""
230
244
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Keep the `x-release-please-version` annotation — release-please uses it to
4
4
  # bump `__version__` in sync with `pyproject.toml` on every release PR.
5
- __version__ = "0.1.30" # x-release-please-version
5
+ __version__ = "0.1.31" # x-release-please-version
6
6
 
7
7
  DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/code"
8
8
  """URL for `deepagents-code` documentation."""
@@ -74,6 +74,7 @@ from deepagents_code.config import (
74
74
  get_default_coding_instructions,
75
75
  get_glyphs,
76
76
  get_langsmith_project_name,
77
+ restore_user_tracing_api_keys,
77
78
  restore_user_tracing_env,
78
79
  settings,
79
80
  )
@@ -1663,6 +1664,7 @@ def create_cli_agent(
1663
1664
  else:
1664
1665
  shell_env.pop("LANGSMITH_PROJECT", None)
1665
1666
  restore_user_tracing_env(shell_env)
1667
+ restore_user_tracing_api_keys(shell_env)
1666
1668
  # Re-apply a launch-time PYTHONPATH that was stripped from the server
1667
1669
  # interpreter but relayed for approval-gated `execute` commands.
1668
1670
  _apply_inherited_pythonpath(shell_env)
@@ -1673,6 +1675,9 @@ def create_cli_agent(
1673
1675
  # `inherit_env=False`: `shell_env` is already a complete, curated
1674
1676
  # copy of `os.environ`. Inheriting again would re-copy `os.environ`
1675
1677
  # and resurrect the popped carrier var, leaking it into `execute`.
1678
+ # `restore_user_tracing_api_keys` above depends on this too: flipping
1679
+ # to `inherit_env=True` would re-copy the agent's overridden
1680
+ # `LANGSMITH_API_KEY` and undo the restore, leaking it into `execute`.
1676
1681
  backend = LocalShellBackend(
1677
1682
  root_dir=root_dir,
1678
1683
  virtual_mode=False,
@@ -1985,7 +1985,8 @@ class DeepAgentsApp(App):
1985
1985
  defer_server_start: Whether to keep app-owned server startup paused
1986
1986
  until the user configures credentials or explicitly picks a model.
1987
1987
  title: Override the Textual `App.title` shown in the optional
1988
- header bar.
1988
+ header bar (shown when `DEEPAGENTS_CODE_SHOW_HEADER` is set or
1989
+ the installation is stale).
1989
1990
 
1990
1991
  When `None`, the class-level `TITLE` is used.
1991
1992
 
@@ -1993,7 +1994,8 @@ class DeepAgentsApp(App):
1993
1994
  sub_title: Override the Textual `App.sub_title` shown in the
1994
1995
  optional header bar.
1995
1996
 
1996
- When `None`, the parent default is used.
1997
+ When `None`, a sandbox label or a stale-install advisory may be
1998
+ substituted; otherwise the parent default is used.
1997
1999
 
1998
2000
  Reassigning `app.sub_title` at runtime updates the header live.
1999
2001
  **kwargs: Additional arguments passed to parent
@@ -2263,6 +2265,34 @@ class DeepAgentsApp(App):
2263
2265
  )
2264
2266
  self.sub_title = f"Sandbox: {display}"
2265
2267
 
2268
+ from deepagents_code.update_check import (
2269
+ installed_days_old,
2270
+ is_installation_stale,
2271
+ )
2272
+
2273
+ self._installation_stale: bool = sub_title is None and is_installation_stale()
2274
+ """Whether the installed version is old enough to force the header banner.
2275
+
2276
+ Set once at construction from the cache-only install-age check. When
2277
+ `True`, `compose` renders the header even without `DEEPAGENTS_CODE_SHOW_HEADER`
2278
+ and the subtitle carries the advisory below — overriding the sandbox
2279
+ subtitle by design.
2280
+ """
2281
+
2282
+ if self._installation_stale:
2283
+ days = installed_days_old()
2284
+ if days is None:
2285
+ # The cache changed between the staleness gate and this read
2286
+ # (e.g. a concurrent `dcode` process). Drop the banner rather
2287
+ # than render "installed version is None days old".
2288
+ self._installation_stale = False
2289
+ else:
2290
+ unit = "day" if days == 1 else "days"
2291
+ self.sub_title = (
2292
+ f"Update available \u2014 installed version is "
2293
+ f"{days} {unit} old (run /update)"
2294
+ )
2295
+
2266
2296
  # Per-turn model overrides
2267
2297
  self._model_override: str | None = None
2268
2298
  """Per-turn model override set via `/model`; `None` uses session default."""
@@ -2770,7 +2800,7 @@ class DeepAgentsApp(App):
2770
2800
  """
2771
2801
  from deepagents_code._env_vars import SHOW_HEADER, is_env_truthy
2772
2802
 
2773
- if is_env_truthy(SHOW_HEADER):
2803
+ if is_env_truthy(SHOW_HEADER) or self._installation_stale:
2774
2804
  yield _StaticHeader(id="app-header")
2775
2805
  # Main chat area with scrollable messages
2776
2806
  # VerticalScroll tracks user scroll intent for better auto-scroll behavior.
@@ -3525,7 +3555,10 @@ class DeepAgentsApp(App):
3525
3555
  """Resolve a `-r` resume intent into a concrete thread ID.
3526
3556
 
3527
3557
  Consumes `self._resume_thread_intent` and resolves it into a concrete
3528
- thread ID. Mutates `self._lc_thread_id` and optionally
3558
+ thread ID. When the intent resolves to an existing thread whose cwd
3559
+ differs from the current one, the cwd-switch prompt is shown with an
3560
+ extra "abort" option; choosing it starts a fresh thread instead of
3561
+ resuming. Mutates `self._lc_thread_id` and optionally
3529
3562
  `self._assistant_id` / `self._server_kwargs`. Does NOT touch
3530
3563
  `self._default_assistant_id` — a one-off resume should not redefine
3531
3564
  the user's persisted default agent. Falls back to a fresh thread on
@@ -3539,7 +3572,6 @@ class DeepAgentsApp(App):
3539
3572
  thread_exists,
3540
3573
  )
3541
3574
 
3542
- resumed_thread_id: str | None = None
3543
3575
  try:
3544
3576
  resume = self._resume_thread_intent
3545
3577
  self._resume_thread_intent = None # consumed
@@ -3549,81 +3581,118 @@ class DeepAgentsApp(App):
3549
3581
 
3550
3582
  default_agent = DEFAULT_ASSISTANT_ID
3551
3583
 
3552
- if resume == "__MOST_RECENT__":
3584
+ # Resolve the candidate thread id before any agent/model mutation,
3585
+ # so an abort only needs to reset the thread id (no rollback).
3586
+ via_most_recent = resume == "__MOST_RECENT__"
3587
+ if via_most_recent:
3553
3588
  agent_filter = (
3554
3589
  self._assistant_id if self._assistant_id != default_agent else None
3555
3590
  )
3556
- thread_id = await get_most_recent(agent_filter)
3557
- if thread_id:
3558
- agent_name = await get_thread_agent(thread_id)
3559
- if agent_name:
3560
- self._assistant_id = agent_name
3561
- if self._server_kwargs:
3562
- self._server_kwargs["assistant_id"] = agent_name
3563
- self._lc_thread_id = thread_id
3564
- resumed_thread_id = thread_id
3565
- self._should_adopt_resumed_model = not self._model_explicitly_set
3566
- else:
3591
+ candidate = await get_most_recent(agent_filter)
3592
+ if not candidate:
3567
3593
  self._lc_thread_id = generate_thread_id()
3594
+ self._resuming = False
3595
+ self._sync_status_connection()
3568
3596
  if agent_filter:
3569
3597
  msg = f"No previous threads for '{agent_filter}', starting new."
3570
3598
  else:
3571
3599
  msg = "No previous threads, starting new."
3572
3600
  self.notify(msg, severity="warning", markup=False)
3601
+ return
3573
3602
  elif await thread_exists(resume):
3574
- self._lc_thread_id = resume
3575
- resumed_thread_id = resume
3576
- self._should_adopt_resumed_model = not self._model_explicitly_set
3577
- if self._assistant_id == default_agent:
3578
- agent_name = await get_thread_agent(resume)
3579
- if agent_name:
3580
- self._assistant_id = agent_name
3581
- if self._server_kwargs:
3582
- self._server_kwargs["assistant_id"] = agent_name
3603
+ candidate = resume
3583
3604
  else:
3584
3605
  # Thread not found — notify + fall back to new thread
3585
3606
  self._lc_thread_id = generate_thread_id()
3607
+ self._resuming = False
3608
+ self._sync_status_connection()
3586
3609
  similar = await find_similar_threads(resume)
3587
3610
  hint = f"Thread '{resume}' not found."
3588
3611
  if similar:
3589
3612
  hint += f" Did you mean: {', '.join(str(t) for t in similar)}?"
3590
3613
  self.notify(hint, severity="warning", timeout=6, markup=False)
3591
- if resumed_thread_id is not None:
3592
- # The cwd-switch offer is a post-resolution convenience. Isolate
3593
- # its failures so they can't fall into the resume-resolution
3594
- # handler below, which would discard the already-resolved thread
3595
- # and misleadingly report "Could not look up thread history."
3596
- try:
3597
- await self._offer_thread_cwd_switch(
3598
- resumed_thread_id,
3599
- restart_server=False,
3600
- )
3601
- except Exception:
3602
- logger.exception(
3603
- "cwd switch offer failed for resumed thread %s",
3604
- resumed_thread_id,
3605
- )
3606
- self.notify(
3607
- "Resumed the thread, but could not check its working "
3608
- "directory. Local context may be stale.",
3609
- severity="warning",
3610
- markup=False,
3611
- )
3614
+ return
3615
+
3616
+ # Commit the resolved thread before the cwd-switch offer so a
3617
+ # failure in that offer leaves the thread resolved (see the
3618
+ # isolation guard below) rather than falling through to the
3619
+ # resume-resolution handler.
3620
+ self._lc_thread_id = candidate
3621
+
3622
+ # The cwd-switch prompt doubles as the resume confirmation: at
3623
+ # launch it carries an extra "abort" option that starts a fresh
3624
+ # session instead of resuming. Isolate its failures so they can't
3625
+ # fall into the resume-resolution handler below, which would
3626
+ # discard the already-resolved thread and misleadingly report
3627
+ # "Could not look up thread history."
3628
+ try:
3629
+ cwd_choice = await self._offer_thread_cwd_switch(
3630
+ candidate,
3631
+ restart_server=False,
3632
+ allow_abort=True,
3633
+ )
3634
+ except Exception:
3635
+ logger.exception(
3636
+ "cwd switch offer failed for resumed thread %s",
3637
+ candidate,
3638
+ )
3639
+ self.notify(
3640
+ "Resumed the thread, but could not check its working "
3641
+ "directory. Local context may be stale.",
3642
+ severity="warning",
3643
+ markup=False,
3644
+ )
3645
+ cwd_choice = "continue"
3646
+
3647
+ if cwd_choice == "abort":
3648
+ # User declined the resume: start a fresh session and skip the
3649
+ # agent/model adoption below so it inherits the launch default.
3650
+ self._lc_thread_id = generate_thread_id()
3651
+ self._resuming = False
3652
+ self._sync_status_connection()
3653
+ self.notify(
3654
+ "Starting a new session.",
3655
+ severity="information",
3656
+ markup=False,
3657
+ )
3658
+ return
3659
+
3660
+ # Confirmed: adopt the thread's agent for this session — always when
3661
+ # resuming the most recent thread (bare `-r`, even over an
3662
+ # explicitly pinned `-a`), and for an explicit `-r <id>` only when
3663
+ # the user hasn't pinned a non-default agent — plus its persisted
3664
+ # model.
3665
+ self._should_adopt_resumed_model = not self._model_explicitly_set
3666
+ if via_most_recent or self._assistant_id == default_agent:
3667
+ agent_name = await get_thread_agent(candidate)
3668
+ if agent_name:
3669
+ self._assistant_id = agent_name
3670
+ if self._server_kwargs:
3671
+ self._server_kwargs["assistant_id"] = agent_name
3612
3672
  except Exception:
3613
3673
  logger.exception("Failed to resolve resume thread %r", resume)
3614
3674
  self._lc_thread_id = generate_thread_id()
3675
+ self._resuming = False
3676
+ self._sync_status_connection()
3615
3677
  self.notify(
3616
3678
  "Could not look up thread history. Starting new session.",
3617
3679
  severity="warning",
3618
3680
  )
3619
3681
  finally:
3682
+ # Sync the resolved (or fresh) thread id into session state before
3683
+ # signaling completion. This must run in `finally` so an early
3684
+ # return — a fallback to a new thread, or the user aborting the
3685
+ # resume — can't leave `session_state.thread_id` pointing at a
3686
+ # thread that was never adopted. `_init_session_state` may run
3687
+ # concurrently and capture a not-yet-final id mid-prompt; this
3688
+ # reconciles it whenever session state already exists. If session
3689
+ # state hasn't been assigned yet, correctness instead relies on
3690
+ # `_init_session_state` reading the now-final `_lc_thread_id` when
3691
+ # it constructs the state.
3692
+ if self._session_state:
3693
+ self._session_state.thread_id = self._lc_thread_id
3620
3694
  self._resume_thread_resolved_event.set()
3621
3695
 
3622
- # Update session state if ready (may still be initializing in a
3623
- # concurrent worker)
3624
- if self._session_state:
3625
- self._session_state.thread_id = self._lc_thread_id
3626
-
3627
3696
  async def _start_server_background(self) -> None:
3628
3697
  """Background worker: resolve resume-thread intent, start server + MCP preload.
3629
3698
 
@@ -7742,8 +7811,7 @@ class DeepAgentsApp(App):
7742
7811
  await self._mount_message(
7743
7812
  AppMessage(
7744
7813
  "LangSmith tracing is not configured. "
7745
- "Run `/auth` and select LangSmith to enable tracing, or set "
7746
- "LANGSMITH_API_KEY and LANGSMITH_TRACING=true.",
7814
+ "Run `/auth` and select LangSmith to enable tracing.",
7747
7815
  ),
7748
7816
  )
7749
7817
  return
@@ -10757,32 +10825,86 @@ class DeepAgentsApp(App):
10757
10825
  if payload.context_tokens > 0:
10758
10826
  self._on_tokens_update(payload.context_tokens)
10759
10827
 
10760
- # 3. Bulk load into store (sets visible window)
10761
- _archived, visible = self._message_store.bulk_load(payload.messages)
10762
-
10763
- # 5. Cache container ref (single query)
10828
+ # 5. Cache container ref (single query). Queried before the store
10829
+ # load so history can be reconciled against widgets already in the
10830
+ # DOM (see below).
10764
10831
  try:
10765
10832
  messages_container = self.query_one("#messages", Container)
10766
10833
  except NoMatches:
10767
10834
  return
10768
10835
 
10769
- # 6-7. Create and mount only visible widgets (max WINDOW_SIZE)
10770
- widgets = [msg_data.to_widget() for msg_data in visible]
10771
- if widgets:
10772
- nodes: list[Widget] = []
10773
- for widget, msg_data in zip(widgets, visible, strict=False):
10774
- nodes.append(widget)
10775
- footer = self._build_message_timestamp_footer(
10776
- msg_data, visible=self._message_timestamps_visible
10836
+ # 3. Reconcile against existing state before loading the store.
10837
+ # Mounting a widget whose ID already exists raises `DuplicateIds`,
10838
+ # which would abort the entire history load. Widened message IDs
10839
+ # make natural collisions vanishingly unlikely, but a re-entrant
10840
+ # load (e.g. a server respawn that re-runs the startup sequence
10841
+ # over a non-cleared store and its surviving widgets) can still
10842
+ # reintroduce an already-present ID. Two guards keep this safe:
10843
+ #
10844
+ # a) Drop payload messages whose ID is already in the store (or
10845
+ # repeated within the payload) before `bulk_load`. Otherwise
10846
+ # `bulk_load` would append duplicate entries to `_messages`,
10847
+ # desyncing the visible window from the DOM and tripping up
10848
+ # later pruning/hydration.
10849
+ # b) Skip mounting any visible message whose ID is already in the
10850
+ # DOM. `bulk_load` returns a window over the *whole* store, so
10851
+ # a surviving pre-existing entry can still surface as a mount
10852
+ # candidate even after (a); its widget already exists.
10853
+ seen: set[str] = set()
10854
+ deduped: list[MessageData] = []
10855
+ for msg_data in payload.messages:
10856
+ if (
10857
+ msg_data.id in seen
10858
+ or self._message_store.get_message(msg_data.id) is not None
10859
+ ):
10860
+ continue
10861
+ seen.add(msg_data.id)
10862
+ deduped.append(msg_data)
10863
+ dropped = len(payload.messages) - len(deduped)
10864
+ if dropped:
10865
+ logger.warning(
10866
+ "Dropped %d duplicate history message(s) for thread %s: "
10867
+ "IDs were already in the store or repeated in the payload",
10868
+ dropped,
10869
+ history_thread_id,
10870
+ )
10871
+
10872
+ # Bulk load into store (sets visible window over the deduped set).
10873
+ _archived, visible = self._message_store.bulk_load(deduped)
10874
+
10875
+ # 6-7. Create and mount the visible widgets (max WINDOW_SIZE),
10876
+ # skipping any whose ID is already mounted (guard (b) above).
10877
+ # `existing_ids` includes footer node IDs, which never collide with
10878
+ # the `msg-`/`asst-` message IDs checked here.
10879
+ existing_ids = {
10880
+ node.id for node in messages_container.children if node.id is not None
10881
+ }
10882
+ mounted: list[tuple[Widget, MessageData]] = []
10883
+ nodes: list[Widget] = []
10884
+ for msg_data in visible:
10885
+ if msg_data.id in existing_ids:
10886
+ logger.debug(
10887
+ "Skipping already-mounted history widget %s in thread %s",
10888
+ msg_data.id,
10889
+ history_thread_id,
10777
10890
  )
10778
- if footer is not None:
10779
- nodes.append(footer)
10891
+ continue
10892
+ existing_ids.add(msg_data.id)
10893
+ widget = msg_data.to_widget()
10894
+ mounted.append((widget, msg_data))
10895
+ nodes.append(widget)
10896
+ footer = self._build_message_timestamp_footer(
10897
+ msg_data, visible=self._message_timestamps_visible
10898
+ )
10899
+ if footer is not None:
10900
+ nodes.append(footer)
10901
+ if nodes:
10780
10902
  await messages_container.mount(*nodes)
10781
10903
 
10782
10904
  # 8. Render content for AssistantMessage after mount
10783
10905
  assistant_updates = [
10784
10906
  widget.set_content(msg_data.content)
10785
- for widget, msg_data in zip(widgets, visible, strict=False)
10907
+ for widget, msg_data in mounted
10786
10908
  if isinstance(widget, AssistantMessage) and msg_data.content
10787
10909
  ]
10788
10910
  if assistant_updates:
@@ -12033,12 +12155,17 @@ class DeepAgentsApp(App):
12033
12155
  child.toggle_body()
12034
12156
  return
12035
12157
  if isinstance(child, ToolCallMessage) and not child.has_class("-grouped"):
12036
- if child.has_output and child.has_expandable_output:
12037
- child.toggle_output()
12038
- return
12158
+ # Prefer the collapsible command/code block when the row has one,
12159
+ # so Ctrl+O matches the "click or Ctrl+O to show command/code"
12160
+ # hint rendered beside it. The output stays reachable by clicking
12161
+ # its own region (see `ToolCallMessage.on_click`); rows without an
12162
+ # expandable command/code block fall through to the output.
12039
12163
  if child.has_expandable_args:
12040
12164
  child.toggle_args()
12041
12165
  return
12166
+ if child.has_output and child.has_expandable_output:
12167
+ child.toggle_output()
12168
+ return
12042
12169
  if child.has_output:
12043
12170
  child.toggle_output()
12044
12171
  return
@@ -15458,6 +15585,7 @@ class DeepAgentsApp(App):
15458
15585
  thread_id: str,
15459
15586
  *,
15460
15587
  restart_server: bool,
15588
+ allow_abort: bool = False,
15461
15589
  ) -> Literal["continue", "abort"]:
15462
15590
  """Offer to switch to a resumed thread's cwd when it differs.
15463
15591
 
@@ -15467,11 +15595,16 @@ class DeepAgentsApp(App):
15467
15595
  switch replaces the app-owned server so the backend runs in the
15468
15596
  new cwd. When False (launch-time resume), the server has not
15469
15597
  started yet, so only the process cwd is changed.
15598
+ allow_abort: When True (launch-time `-r` resume), the prompt offers a
15599
+ third "abort" option that declines the resume entirely.
15470
15600
 
15471
15601
  Returns:
15472
- `"continue"` when resume may proceed, or `"abort"` when a requested
15473
- switch was accepted but failed (the caller should stop
15474
- the resume).
15602
+ `"continue"` when resume may proceed, or `"abort"` when the user
15603
+ declined the resume or a requested switch was accepted but
15604
+ failed (the caller should stop the resume). The two abort
15605
+ sources are mode-exclusive: the user-declined abort fires only
15606
+ when `allow_abort` is True, and the switch-failed abort only
15607
+ when `restart_server` is True.
15475
15608
  """
15476
15609
  target = await self._thread_cwd_mismatch(thread_id)
15477
15610
  if target is None:
@@ -15487,8 +15620,11 @@ class DeepAgentsApp(App):
15487
15620
  current_cwd=self._cwd,
15488
15621
  thread_cwd=str(target),
15489
15622
  project_settings_change_detected=project_settings_change_detected,
15623
+ allow_abort=allow_abort,
15490
15624
  )
15491
15625
  )
15626
+ if choice == "abort":
15627
+ return "abort"
15492
15628
  if choice == "switch":
15493
15629
  if restart_server:
15494
15630
  return await self._replace_server_after_cwd_switch(target)
@@ -15888,6 +16024,12 @@ class DeepAgentsApp(App):
15888
16024
  if provider and not parsed:
15889
16025
  display = f"{provider}:{model_name}"
15890
16026
 
16027
+ # Provider package imports (e.g. langchain_google_genai) can take a
16028
+ # noticeable moment; show an animated busy indicator so it doesn't look
16029
+ # frozen. The work itself already runs off the event loop via
16030
+ # `asyncio.to_thread`, so the UI stays responsive meanwhile.
16031
+ if self._status_bar:
16032
+ self._status_bar.set_busy("Switching model")
15891
16033
  try:
15892
16034
  result = await asyncio.to_thread(
15893
16035
  _create_model_with_deepagents_import_lock,
@@ -15907,6 +16049,9 @@ class DeepAgentsApp(App):
15907
16049
  ErrorMessage(_build_model_switch_error_body(exc)),
15908
16050
  )
15909
16051
  return
16052
+ finally:
16053
+ if self._status_bar:
16054
+ self._status_bar.set_busy("")
15910
16055
 
15911
16056
  # Set the model override for ConfigurableModelMiddleware.
15912
16057
  # The next stream call passes CLIContext via context= and the
@@ -16228,8 +16373,9 @@ async def run_textual_app(
16228
16373
  defer_server_start: Whether to keep app-owned server startup paused
16229
16374
  until credentials or a model are configured from inside the TUI.
16230
16375
  title: Override the Textual `App.title` shown in the optional header
16231
- bar (gated on `DEEPAGENTS_CODE_SHOW_HEADER`). When `None`, the
16232
- default `"Deep Agents"` is used.
16376
+ bar (gated on `DEEPAGENTS_CODE_SHOW_HEADER`, or shown automatically
16377
+ when the installation is stale). When `None`, the default
16378
+ `"Deep Agents"` is used.
16233
16379
  sub_title: Override the Textual `App.sub_title` shown in the optional
16234
16380
  header bar.
16235
16381