deepagents-code 0.1.59__tar.gz → 0.1.60__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 (500) hide show
  1. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/CHANGELOG.md +21 -0
  2. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/COMMANDS.md +1 -1
  3. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/PKG-INFO +1 -1
  4. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/THREAT_MODEL.md +4 -3
  5. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_ask_user_types.py +154 -8
  6. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_build_info.py +1 -1
  7. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_env_vars.py +13 -0
  8. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_textual_patches.py +110 -3
  9. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_version.py +1 -1
  10. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/agent.py +0 -60
  11. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/app.py +170 -64
  12. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/approval_mode.py +9 -7
  13. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/ask_user.py +142 -130
  14. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auto_mode.py +2 -11
  15. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/config.py +34 -2
  16. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/command_registry.py +1 -1
  17. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/config.py +151 -37
  18. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/config_manifest.py +164 -0
  19. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/model_config.py +111 -12
  20. deepagents_code-0.1.60/deepagents_code/tui/key_hints.py +31 -0
  21. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/cold_cache.py +2 -1
  22. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/__init__.py +6 -4
  23. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +1 -0
  24. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/agent_selector.py +11 -7
  25. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/approval.py +1 -1
  26. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/ask_user.py +6 -5
  27. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/auth.py +125 -15
  28. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/chat_input.py +138 -0
  29. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/debug_console.py +70 -5
  30. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/effort_selector.py +3 -1
  31. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/launch_init.py +2 -1
  32. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_viewer.py +4 -1
  33. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/message_store.py +2 -2
  34. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/messages.py +1 -1
  35. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/model_selector.py +7 -3
  36. deepagents_code-0.1.60/deepagents_code/tui/widgets/notification_center.py +1044 -0
  37. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/notification_detail.py +4 -2
  38. deepagents_code-0.1.60/deepagents_code/tui/widgets/notification_settings.py +15 -0
  39. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/theme_selector.py +6 -5
  40. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_available.py +4 -2
  41. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/pyproject.toml +1 -1
  42. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_agent.py +10 -31
  43. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_app.py +639 -18
  44. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ask_user_middleware.py +333 -205
  45. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ask_user_types.py +52 -1
  46. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auto_mode.py +8 -2
  47. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config.py +57 -0
  48. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config_manifest.py +156 -0
  49. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration.py +25 -0
  50. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug_console.py +52 -0
  51. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_end_to_end.py +105 -13
  52. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_model_config.py +172 -5
  53. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reload.py +246 -5
  54. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_textual_patches.py +109 -1
  55. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +2 -0
  56. deepagents_code-0.1.60/tests/unit_tests/tui/test_key_hints.py +33 -0
  57. deepagents_code-0.1.60/tests/unit_tests/tui/test_modal_footer_layout.py +200 -0
  58. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/test_textual_adapter.py +6 -1
  59. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_agent_selector.py +1 -0
  60. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_approval.py +2 -2
  61. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_auth_widgets.py +231 -8
  62. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_chat_input.py +227 -1
  63. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +1 -0
  64. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_model_selector.py +6 -0
  65. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_notification_center.py +201 -6
  66. deepagents_code-0.1.60/tests/unit_tests/tui/widgets/test_notification_settings.py +313 -0
  67. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/uv.lock +1 -1
  68. deepagents_code-0.1.59/deepagents_code/_tool_errors.py +0 -20
  69. deepagents_code-0.1.59/deepagents_code/tui/widgets/notification_center.py +0 -464
  70. deepagents_code-0.1.59/deepagents_code/tui/widgets/notification_settings.py +0 -179
  71. deepagents_code-0.1.59/tests/unit_tests/tui/widgets/test_notification_settings.py +0 -145
  72. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/.gitignore +0 -0
  73. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/AGENTS.md +0 -0
  74. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/ARCHITECTURE.md +0 -0
  75. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/DEVELOPMENT.md +0 -0
  76. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/HOOKS.md +0 -0
  77. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/LICENSE +0 -0
  78. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/Makefile +0 -0
  79. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/PRICING.md +0 -0
  80. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/README.md +0 -0
  81. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/__init__.py +0 -0
  82. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/__main__.py +0 -0
  83. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_cli_context.py +0 -0
  84. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_constants.py +0 -0
  85. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_debug.py +0 -0
  86. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_debug_buffer.py +0 -0
  87. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_dep_floor_check.py +0 -0
  88. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_fake_models.py +0 -0
  89. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_git.py +0 -0
  90. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_glm_5p2_profile.py +0 -0
  91. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_invocation.py +0 -0
  92. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_markdown.py +0 -0
  93. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_paths.py +0 -0
  94. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_repository_bounds.py +0 -0
  95. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_server_config.py +0 -0
  96. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_session_stats.py +0 -0
  97. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_startup_error.py +0 -0
  98. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_testing_models.py +0 -0
  99. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_tool_stream.py +0 -0
  100. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_tracing.py +0 -0
  101. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/acp.py +0 -0
  102. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/app.tcss +0 -0
  103. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auth_display.py +0 -0
  104. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auth_store.py +0 -0
  105. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/__init__.py +0 -0
  106. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
  107. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
  108. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  109. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  110. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  111. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  112. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/bundled_prices.README.md +0 -0
  113. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/bundled_prices.json +0 -0
  114. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/__init__.py +0 -0
  115. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/__init__.py +0 -0
  116. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/auth.py +0 -0
  117. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/extras.py +0 -0
  118. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/mcp.py +0 -0
  119. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/tools.py +0 -0
  120. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/__init__.py +0 -0
  121. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/server.py +0 -0
  122. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/server_manager.py +0 -0
  123. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/non_interactive.py +0 -0
  124. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/remote_client.py +0 -0
  125. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/clipboard.py +0 -0
  126. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/cold_cache.py +0 -0
  127. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configurable_model.py +0 -0
  128. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/__init__.py +0 -0
  129. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/paths.py +0 -0
  130. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/providers.py +0 -0
  131. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/resolver.py +0 -0
  132. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/service.py +0 -0
  133. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/types.py +0 -0
  134. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/writer.py +0 -0
  135. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/cost_tracking.py +0 -0
  136. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/default_agent_prompt.md +0 -0
  137. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/diff_utils.py +0 -0
  138. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/doctor.py +0 -0
  139. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/editor.py +0 -0
  140. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/event_bus.py +0 -0
  141. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/extras_info.py +0 -0
  142. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/file_ops.py +0 -0
  143. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/formatting.py +0 -0
  144. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_rubric.py +0 -0
  145. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_state_notice.py +0 -0
  146. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_tools.py +0 -0
  147. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/__init__.py +0 -0
  148. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/capabilities.py +0 -0
  149. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/client.py +0 -0
  150. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/client_lifecycle.py +0 -0
  151. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/context.py +0 -0
  152. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/engine.py +0 -0
  153. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/env.py +0 -0
  154. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/envelope.py +0 -0
  155. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/interrupt.py +0 -0
  156. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/legacy.py +0 -0
  157. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/loading.py +0 -0
  158. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/manager.py +0 -0
  159. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/migration.py +0 -0
  160. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/__init__.py +0 -0
  161. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/adapters.py +0 -0
  162. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/config.py +0 -0
  163. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/domain.py +0 -0
  164. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/transport.py +0 -0
  165. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/wire.py +0 -0
  166. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/permissions.py +0 -0
  167. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/presenter.py +0 -0
  168. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/projection.py +0 -0
  169. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/reducer.py +0 -0
  170. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/runner.py +0 -0
  171. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/runtime.py +0 -0
  172. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/server_middleware.py +0 -0
  173. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/snapshot.py +0 -0
  174. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/tools.py +0 -0
  175. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/transcript.py +0 -0
  176. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/trust.py +0 -0
  177. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
  178. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/input.py +0 -0
  179. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/__init__.py +0 -0
  180. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/openai_codex.py +0 -0
  181. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_config.py +0 -0
  182. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_factory.py +0 -0
  183. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_provider.py +0 -0
  184. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_registry.py +0 -0
  185. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/iterm_cursor_guide.py +0 -0
  186. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/json_types.py +0 -0
  187. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/local_context.py +0 -0
  188. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/main.py +0 -0
  189. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/managed_tools.py +0 -0
  190. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_auth.py +0 -0
  191. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_config.py +0 -0
  192. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_disabled.py +0 -0
  193. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_login_service.py +0 -0
  194. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_oauth_ui.py +0 -0
  195. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/__init__.py +0 -0
  196. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/_registry.py +0 -0
  197. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/base.py +0 -0
  198. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/github.py +0 -0
  199. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/slack.py +0 -0
  200. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_tools.py +0 -0
  201. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/media_utils.py +0 -0
  202. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/memory_guard.py +0 -0
  203. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/notifications.py +0 -0
  204. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/offload.py +0 -0
  205. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/offload_middleware.py +0 -0
  206. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/onboarding.py +0 -0
  207. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/output.py +0 -0
  208. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/paste_collapse.py +0 -0
  209. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/__init__.py +0 -0
  210. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/_json.py +0 -0
  211. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/__init__.py +0 -0
  212. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/hooks.py +0 -0
  213. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/mcp.py +0 -0
  214. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/skills.py +0 -0
  215. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
  216. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/commands_cli.py +0 -0
  217. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/discovery.py +0 -0
  218. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/manifest.py +0 -0
  219. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/marketplace.py +0 -0
  220. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/models.py +0 -0
  221. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/store.py +0 -0
  222. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/substitution.py +0 -0
  223. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/project_utils.py +0 -0
  224. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/py.typed +0 -0
  225. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/reasoning_effort.py +0 -0
  226. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/reliable_rubric.py +0 -0
  227. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/resume_state.py +0 -0
  228. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/server_graph.py +0 -0
  229. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/sessions.py +0 -0
  230. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/__init__.py +0 -0
  231. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/commands.py +0 -0
  232. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/invocation.py +0 -0
  233. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/load.py +0 -0
  234. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/merge.py +0 -0
  235. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/trust.py +0 -0
  236. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/state_migration.py +0 -0
  237. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/subagents.py +0 -0
  238. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/system_prompt.md +0 -0
  239. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/terminal_capabilities.py +0 -0
  240. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/terminal_escape.py +0 -0
  241. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/theme.py +0 -0
  242. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tool_catalog.py +0 -0
  243. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tool_display.py +0 -0
  244. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tools.py +0 -0
  245. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/__init__.py +0 -0
  246. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/__init__.py +0 -0
  247. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/content.py +0 -0
  248. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/models.py +0 -0
  249. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/state.py +0 -0
  250. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
  251. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/resume_compact.py +0 -0
  252. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/screens/__init__.py +0 -0
  253. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/textual_adapter.py +0 -0
  254. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/__init__.py +0 -0
  255. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
  256. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
  257. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
  258. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_links.py +0 -0
  259. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_paste_textarea.py +0 -0
  260. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/auto_mode_notice.py +0 -0
  261. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/autocomplete.py +0 -0
  262. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/codex_auth.py +0 -0
  263. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/context_usage.py +0 -0
  264. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/cwd_switch.py +0 -0
  265. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/diff.py +0 -0
  266. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/goal_review.py +0 -0
  267. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/goal_status.py +0 -0
  268. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/history.py +0 -0
  269. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/install_confirm.py +0 -0
  270. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/loading.py +0 -0
  271. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_login.py +0 -0
  272. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
  273. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
  274. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/skill_trust.py +0 -0
  275. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/startup_tip.py +0 -0
  276. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/status.py +0 -0
  277. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/subagent_panel.py +0 -0
  278. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
  279. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/thread_selector.py +0 -0
  280. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
  281. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
  282. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_confirm.py +0 -0
  283. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_progress.py +0 -0
  284. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/welcome.py +0 -0
  285. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
  286. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/ui.py +0 -0
  287. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/unicode_security.py +0 -0
  288. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/update_check.py +0 -0
  289. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/arxiv-search/SKILL.md +0 -0
  290. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  291. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/langgraph-docs/SKILL.md +0 -0
  292. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/SKILL.md +0 -0
  293. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  294. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  295. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/web-research/SKILL.md +0 -0
  296. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/hatch_build.py +0 -0
  297. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/images/tui.png +0 -0
  298. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/check_imports.py +0 -0
  299. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/debug_server.sh +0 -0
  300. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/generate_commands_catalog.py +0 -0
  301. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/install.sh +0 -0
  302. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/README.md +0 -0
  303. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/__init__.py +0 -0
  304. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/__init__.py +0 -0
  305. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  306. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
  307. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  308. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/conftest.py +0 -0
  309. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_acp_mode.py +0 -0
  310. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_auto_approve_remote.py +0 -0
  311. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_compact_resume.py +0 -0
  312. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
  313. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_offload_server_side.py +0 -0
  314. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_sandbox_factory.py +0 -0
  315. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_sandbox_operations.py +0 -0
  316. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/__init__.py +0 -0
  317. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/__init__.py +0 -0
  318. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/__init__.py +0 -0
  319. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_auth.py +0 -0
  320. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_extras.py +0 -0
  321. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_mcp.py +0 -0
  322. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_tools.py +0 -0
  323. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/conftest.py +0 -0
  324. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
  325. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/__init__.py +0 -0
  326. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/models/__init__.py +0 -0
  327. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/models/test_models.py +0 -0
  328. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
  329. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_configuration.py +0 -0
  330. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_engine.py +0 -0
  331. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_execution.py +0 -0
  332. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_manager.py +0 -0
  333. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_presenter.py +0 -0
  334. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_server_lifecycle.py +0 -0
  335. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_transcript.py +0 -0
  336. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_trust.py +0 -0
  337. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/__init__.py +0 -0
  338. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_marketplace.py +0 -0
  339. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_plugin_hooks.py +0 -0
  340. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_plugins_p0.py +0 -0
  341. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_store.py +0 -0
  342. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/__init__.py +0 -0
  343. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_commands.py +0 -0
  344. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_load.py +0 -0
  345. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_merge.py +0 -0
  346. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_skill_trust.py +0 -0
  347. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_skills_json.py +0 -0
  348. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
  349. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/__init__.py +0 -0
  350. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/conftest.py +0 -0
  351. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +0 -0
  352. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
  353. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test__tool_stream.py +0 -0
  354. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_acp.py +0 -0
  355. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_agent_friendly.py +0 -0
  356. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_approval_mode.py +0 -0
  357. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_args.py +0 -0
  358. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_display.py +0 -0
  359. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_store.py +0 -0
  360. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
  361. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_charset.py +0 -0
  362. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_clipboard.py +0 -0
  363. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
  364. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cold_cache.py +0 -0
  365. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_command_registry.py +0 -0
  366. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_compact_tool.py +0 -0
  367. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config_recursion_limit.py +0 -0
  368. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configurable_model.py +0 -0
  369. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration_resolution.py +0 -0
  370. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration_resolver.py +0 -0
  371. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cost_tracking.py +0 -0
  372. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cursor_blink.py +0 -0
  373. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cursor_style.py +0 -0
  374. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug.py +0 -0
  375. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug_buffer.py +0 -0
  376. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_dep_floor_check.py +0 -0
  377. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_diff_utils.py +0 -0
  378. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_doctor.py +0 -0
  379. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_editor.py +0 -0
  380. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_env_vars.py +0 -0
  381. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_event_bus.py +0 -0
  382. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_exception_handling.py +0 -0
  383. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_extras_info.py +0 -0
  384. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_file_ops.py +0 -0
  385. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_formatting.py +0 -0
  386. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_git.py +0 -0
  387. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
  388. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_criteria_client.py +0 -0
  389. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_rubric.py +0 -0
  390. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_state_notice.py +0 -0
  391. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_state_persistence.py +0 -0
  392. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_tools.py +0 -0
  393. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_hatch_build.py +0 -0
  394. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_hooks.py +0 -0
  395. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_imports.py +0 -0
  396. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_input_parsing.py +0 -0
  397. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_install_command.py +0 -0
  398. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_install_script.py +0 -0
  399. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_invocation.py +0 -0
  400. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  401. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_json_types.py +0 -0
  402. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_local_context.py +0 -0
  403. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main.py +0 -0
  404. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main_acp_mode.py +0 -0
  405. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main_args.py +0 -0
  406. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_managed_tools.py +0 -0
  407. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_auth.py +0 -0
  408. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_config.py +0 -0
  409. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_disabled.py +0 -0
  410. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_login_service.py +0 -0
  411. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  412. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_tools.py +0 -0
  413. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_media_utils.py +0 -0
  414. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_memory_guard.py +0 -0
  415. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_model_switch.py +0 -0
  416. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_non_interactive.py +0 -0
  417. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_notifications.py +0 -0
  418. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_offload.py +0 -0
  419. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_onboarding.py +0 -0
  420. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  421. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_output.py +0 -0
  422. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_paths.py +0 -0
  423. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reasoning_effort.py +0 -0
  424. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reliable_rubric.py +0 -0
  425. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_remote_client.py +0 -0
  426. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_repository_bounds.py +0 -0
  427. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_resume_state.py +0 -0
  428. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_rubric_cli.py +0 -0
  429. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_config.py +0 -0
  430. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_factory.py +0 -0
  431. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_provider.py +0 -0
  432. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_registry.py +0 -0
  433. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server.py +0 -0
  434. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_config.py +0 -0
  435. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_graph.py +0 -0
  436. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_helpers.py +0 -0
  437. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_manager.py +0 -0
  438. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_session_stats.py +0 -0
  439. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sessions.py +0 -0
  440. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_shell_allow_list.py +0 -0
  441. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_skill_invocation.py +0 -0
  442. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_startup_blocking.py +0 -0
  443. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  444. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_state_migration.py +0 -0
  445. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_subagents.py +0 -0
  446. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  447. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_escape.py +0 -0
  448. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  449. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_theme.py +0 -0
  450. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_threads_resume.py +0 -0
  451. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tool_catalog.py +0 -0
  452. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tool_display.py +0 -0
  453. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tracing.py +0 -0
  454. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tracing_replicas.py +0 -0
  455. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_transcript_virtualization.py +0 -0
  456. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ui.py +0 -0
  457. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_unicode_security.py +0 -0
  458. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_update_check.py +0 -0
  459. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_version.py +0 -0
  460. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/__init__.py +0 -0
  461. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_current_thread.py +0 -0
  462. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  463. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
  464. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/__init__.py +0 -0
  465. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/__init__.py +0 -0
  466. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
  467. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/test_cold_cache.py +0 -0
  468. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
  469. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/__init__.py +0 -0
  470. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_ask_user.py +0 -0
  471. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +0 -0
  472. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
  473. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
  474. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
  475. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
  476. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
  477. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_history.py +0 -0
  478. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_inline_prompt.py +0 -0
  479. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
  480. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
  481. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_links.py +0 -0
  482. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
  483. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
  484. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
  485. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_message_store.py +0 -0
  486. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_messages.py +0 -0
  487. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
  488. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
  489. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
  490. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_startup_tip.py +0 -0
  491. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_status.py +0 -0
  492. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_subagent_panel.py +0 -0
  493. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
  494. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_thread_selector.py +0 -0
  495. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
  496. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
  497. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
  498. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
  499. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_welcome.py +0 -0
  500. {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_yolo_mode_notice.py +0 -0
@@ -2,6 +2,27 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.60](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.59...deepagents-code==0.1.60) (2026-08-23)
6
+
7
+ ### Features
8
+
9
+ - Added `editable` trace metadata ([#5737](https://github.com/langchain-ai/deepagents/issues/5737)) ([23b83ad](https://github.com/langchain-ai/deepagents/commit/23b83ad50f63d241d0069a3dc426d43b211adf2e)).
10
+ - Added shell command highlighting in the chat input ([#5675](https://github.com/langchain-ai/deepagents/issues/5675)) ([d711bc6](https://github.com/langchain-ai/deepagents/commit/d711bc61300090181dc89e3e116e8b343fb65425)).
11
+ - Made project `.env` loading configurable ([#5726](https://github.com/langchain-ai/deepagents/issues/5726)) ([995cad6](https://github.com/langchain-ai/deepagents/commit/995cad67519af294851282133f8c40f643807c88)).
12
+ - Unified notification center and settings ([#5698](https://github.com/langchain-ai/deepagents/issues/5698)) ([9767f42](https://github.com/langchain-ai/deepagents/commit/9767f420c622a31a7511c4601739534ddc6062a7)).
13
+
14
+ ### Bug Fixes
15
+
16
+ - Blocked dotenv git config injection keys ([#5723](https://github.com/langchain-ai/deepagents/issues/5723)) ([328f916](https://github.com/langchain-ai/deepagents/commit/328f9160e0f95a459be8ad57f76e7178b24a3ef8)).
17
+ - Persisted Auto approval mode between sessions and simplified Auto fallback copy ([#5665](https://github.com/langchain-ai/deepagents/issues/5665)) ([3ac059e](https://github.com/langchain-ai/deepagents/commit/3ac059e1574963fe216692642aa1b1a4044daaa9)), ([#5670](https://github.com/langchain-ai/deepagents/issues/5670)) ([42afcde](https://github.com/langchain-ai/deepagents/commit/42afcded97029070f393232778c84aaf3b69fb1c)).
18
+ - Fixed recognition of in-flight trace messages ([#5738](https://github.com/langchain-ai/deepagents/issues/5738)) ([f1d1f63](https://github.com/langchain-ai/deepagents/commit/f1d1f632812a85646d25ac2f3d2d7f39b65a0b49)).
19
+ - Increased the warm limit to 800 ([#5728](https://github.com/langchain-ai/deepagents/issues/5728)) ([f954cde](https://github.com/langchain-ai/deepagents/commit/f954cde37f1171adc2ec3f1516a0393bded47e82)).
20
+ - Improved text selection by supporting `Shift` + `click` to extend selections ([#5732](https://github.com/langchain-ai/deepagents/issues/5732)) ([e05931b](https://github.com/langchain-ai/deepagents/commit/e05931b3016ed3d1500df0c5b77402f457ee5686)).
21
+ - Polished notification settings by removing expand flicker and the trailing disclosure glyph ([#5734](https://github.com/langchain-ai/deepagents/issues/5734)) ([5397812](https://github.com/langchain-ai/deepagents/commit/5397812ad5f217cd84f871f121cf9ea8f3d63f4f)).
22
+ - Improved authentication footers with contextual actions ([#5690](https://github.com/langchain-ai/deepagents/issues/5690)) ([074a501](https://github.com/langchain-ai/deepagents/commit/074a5019e1f3edfd589614774958400d051e5fe1)).
23
+ - Standardized modal navigation hints ([#5699](https://github.com/langchain-ai/deepagents/issues/5699)) ([85c6833](https://github.com/langchain-ai/deepagents/commit/85c6833734a547e968221c1199a769d7aac69430)).
24
+ - Aligned wrapped debug snapshot values ([#5727](https://github.com/langchain-ai/deepagents/issues/5727)) ([1f74959](https://github.com/langchain-ai/deepagents/commit/1f7495949232fe2e3e3328b6ff9054c202002f95)).
25
+
5
26
  ## [0.1.59](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.58...deepagents-code==0.1.59) (2026-08-20)
6
27
 
7
28
  ### Features
@@ -33,7 +33,7 @@ aliases, descriptions, visibility, or hidden-command metadata.
33
33
  | `/manual` | | Switch to Manual approval mode |
34
34
  | `/mcp` | | Manage MCP servers and authentication |
35
35
  | `/model` | | Switch models or edit model settings |
36
- | `/notifications` | | Configure warning notifications |
36
+ | `/notifications` | | Review notifications and configure warning settings |
37
37
  | `/offload` | `/compact` | Summarize and offload older messages to free context |
38
38
  | `/plugins` | | Manage plugins |
39
39
  | `/quit` | `/q` | Exit app |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: deepagents-code
3
- Version: 0.1.59
3
+ Version: 0.1.60
4
4
  Summary: Terminal coding agent built on the Deep Agents SDK - works with any model, with persistent memory, customizable skills, subagents, and approval controls.
5
5
  Project-URL: Homepage, https://www.langchain.com/dcode
6
6
  Project-URL: Documentation, https://docs.langchain.com/oss/deepagents/code/overview
@@ -260,7 +260,7 @@
260
260
  - **Inside**: `config._create_model_from_class` validates `class_path` format (`module:ClassName`), imports the module via `importlib.import_module()`, and checks `issubclass(cls, BaseChatModel)` before instantiation.
261
261
  - **Outside**: Module-level code in the imported module executes unconditionally during `import_module()`. The `issubclass` check only runs after import. Any side effects (file I/O, network calls, subprocess spawning) in the module's top-level scope execute before the type check.
262
262
  - **Crossing mechanism**: `importlib.import_module(module_path)` in `config._create_model_from_class`.
263
- - **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
263
+ - **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The denylist is best-effort: it enumerates environment variables known to reach a code-execution consumer (a shell's startup hook, the dynamic linker, an interpreter's startup path) and cannot claim completeness — any tool `dcode` spawns that honors an environment-driven execution hook not yet in the list remains a live vector until the key is added. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
264
264
  - **Outside (dotenv)**: All other `.env` keys are applied to the process environment, and any project file in the working directory (`.env`, `Makefile`, build scripts) can still influence execution. See T12.
265
265
 
266
266
  #### TB12: Managed Config → Runtime
@@ -453,7 +453,7 @@
453
453
  #### T12: Project `.env` Injects Shell Interpreter Startup Hooks
454
454
 
455
455
  - **Flow**: DF10 (project `.env` → process environment) → bash subprocess startup (DF19)
456
- - **Description**: `config._load_dotenv` discovers the nearest project `.env` by walking up from the working directory and applies its values to the process environment (`override=False`, so shell-exported values still win). Bash treats several environment variables as startup hooks — `BASH_ENV` and `ENV` name a file that is sourced when a non-interactive shell starts. Because Deep Agents Code runs its own local-context detection through Bash at startup (`local_context.build_detect_script`) and spawns shells for the `execute` tool, a project `.env` that sets one of these keys could run attacker-controlled scripts inside the `dcode` process *before* any model-requested tool call or HITL approval prompt. The broader trust boundary is that running `dcode` in a project directory lets that project influence the process environment.
456
+ - **Description**: `config._load_dotenv` discovers the nearest project `.env` by walking up from the working directory and applies its values to the process environment (`override=False`, so shell-exported values still win). Bash treats several environment variables as startup hooks — `BASH_ENV` and `ENV` name a file that is sourced when a non-interactive shell starts. Because Deep Agents Code runs its own local-context detection through Bash at startup (`local_context.build_detect_script`) and spawns shells for the `execute` tool, a project `.env` that sets one of these keys could run attacker-controlled scripts inside the `dcode` process *before* any model-requested tool call or HITL approval prompt. The broader trust boundary is that running `dcode` in a project directory lets that project influence the process environment. The mitigation is a key denylist (`config._DOTENV_DENIED_ENV_KEYS`) covering known execution-hook consumers (shell startup, dynamic linker, interpreter startup/paths, askpass hijack); it is a best-effort enumeration, not a closed set, so an execution hook consumed by some other spawned tool remains viable until its keys are added to the list.
457
457
  - **Preconditions**: (1) User launches `dcode` in a directory containing an attacker-controlled `.env` (for example, a freshly cloned untrusted repository); (2) the `.env` sets a shell startup-hook key that is not already exported in the user's shell (dotenv uses `override=False`).
458
458
 
459
459
  #### T13: First-Token Shell Allow-List Bypass via Interpreters/Wrappers
@@ -478,7 +478,7 @@
478
478
  | LLM output | DF6, DF7 | T1, T2, T3, T4, T13, T14| HITL gate; shell allow-list; Unicode/URL warnings on tool args; Auto classifier review | Project | LLM-generated tool args not scanned for injection beyond Unicode/URL; shell allow-list matches only the command's first token, so allow-listed interpreters/wrappers bypass it (T13); Auto classifier review quality follows the user-selected classifier model, and the classifier reads untrusted tool arguments, prior output, and model-authored `ask_user` question text (T14) |
479
479
  | Tool/function results | DF9, DF11 | T1 | Unicode warning on URL args; `markdownify` HTML conversion | Shared | Tool *results* pass to context without prompt-injection scan |
480
480
  | URL-fetched content | DF8, DF9 | T1 | `check_url_safety` on URL arg; HTML→markdown conversion | Shared | Markup-embedded instructions survive markdownify; no LLM-layer guardrail |
481
- | Configuration | DF10, DF12, DF15, DF23| T9, T10, T12, T14 | Dotenv shell-env precedence; TOML schema; MCP schema + allow/deny lists; JSON structure check; `class_path` format check; project-`.env` denylist for the Auto classifier model | User | Project `.env` can set shell startup-hook vars; `class_path` executes module code before type check; MCP env dict unfiltered; Auto classifier strength is a user choice with no floor enforced (T14) |
481
+ | Configuration | DF10, DF12, DF15, DF23| T9, T10, T12, T14 | Dotenv shell-env precedence; TOML schema; MCP schema + allow/deny lists; JSON structure check; `class_path` format check; dotenv denylist for execution-hook env keys and project-`.env` trust vars | User | Dotenv denylist is best-effort execution-hook env keys consumed by tools not yet enumerated still reach subprocesses; `class_path` executes module code before type check; MCP env dict unfiltered; Auto classifier strength is a user choice with no floor enforced (T14) |
482
482
  | Session restore | DF14 | T5 | OS file permissions; SQLite | Project | Unencrypted at rest |
483
483
  | Server IPC (env vars) | DF18 | T6 | `ServerConfig` serialization; parent env passed to child | Project | Provider API keys flow to server subprocess; system prompt in env |
484
484
  | Host environment | DF19, DF20 | T7 | Static script; exit code check; 30s timeout | Shared | Makefile content injected into system prompt without sanitization |
@@ -545,3 +545,4 @@ Threats that appear valid in isolation but fall outside project responsibility b
545
545
  | 2026-08-03 | manual update | Added T14 (a weaker Auto classifier model weakens action review) under TB2, covering the selectable classifier (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, `/auto model`), its restriction to trusted config surfaces via `config._PROJECT_DOTENV_DENIED_ENV_KEYS`, and its fail-closed construction behavior (deny, then latch to human approval; never fall back to the main model). Extended the "LLM output" and "Configuration" input-coverage rows with T14 |
546
546
  | 2026-08-04 | manual update | Extended T14 for the configurable Auto classifier review deadline (`DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT`, `[models].auto_classifier_timeout`): bounded by `config_manifest.resolve_auto_classifier_timeout` between a floor and ceiling so the deadline cannot be removed, denied from a project `.env` via `config._PROJECT_DOTENV_DENIED_ENV_KEYS`, and fail-closed on expiry |
547
547
  | 2026-08-17 | manual update | Extended T14 for `ask_user` question text as a classifier injection source: the receipt attests display and answer, not content, so a question claiming prior or blanket authorization is untrusted content; recorded the `_CLASSIFIER_POLICY` clauses that keep a paired question to an action/target description matched against canonical arguments. Narrowed the T14 "deterministic allow/deny" guard wording, which overstated the deny side: deterministic denies do not cover the Deny categories, and an affirmative classifier allow is not re-checked downstream |
548
+ | 2026-08-21 | manual update | Clarified that the dotenv execution-hook denylist (`config._DOTENV_DENIED_ENV_KEYS`) is a best-effort enumeration of known code-execution consumers, not a closed set: TB11's inside-detail and T12's description now state this explicitly, and the Configuration input-coverage gap was reworded from the stale "project `.env` can set shell startup-hook vars" (denylisted since #4288) to the actual residual — execution-hook keys consumed by not-yet-enumerated tools still reach subprocesses |
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  import json
15
15
  from typing import Annotated, Literal, NotRequired, assert_never, get_args
16
16
 
17
- from pydantic import Field
17
+ from pydantic import AfterValidator, Field
18
18
  from typing_extensions import TypedDict
19
19
 
20
20
  QuestionType = Literal["text", "multiple_choice", "multi_select"]
@@ -155,6 +155,65 @@ def ask_user_answer_is_empty(answer: str, question_type: object) -> bool:
155
155
  return not answer.strip()
156
156
 
157
157
 
158
+ def _validate_question_text(text: str) -> str:
159
+ """Reject a `question` that is empty or all whitespace.
160
+
161
+ This is the only rule that *rejects* blank question text.
162
+ `messages._ask_user_question_count` also tests it, but degrades to a count
163
+ of zero instead of rejecting.
164
+
165
+ Do not reorder this annotation and the `Field` beside it. As the inner
166
+ annotation it runs before `min_length=1`, which therefore never rejects
167
+ anything — that constraint is kept only because it is what puts
168
+ `minLength: 1` in the JSON schema the model reads. Swapping the two moves
169
+ the empty-string rejection onto `min_length` and changes the error the
170
+ model sees from this function's message to `string_too_short`. A string
171
+ like `" "` would render as a visually blank prompt.
172
+
173
+ Args:
174
+ text: The parsed `question` text to check.
175
+
176
+ Returns:
177
+ The same `text`, unchanged.
178
+
179
+ Raises:
180
+ ValueError: If `text` has no non-whitespace character.
181
+ """
182
+ if not text.strip():
183
+ msg = "question text must not be blank"
184
+ raise ValueError(msg)
185
+ return text
186
+
187
+
188
+ def _validate_choice(choice: Choice) -> Choice:
189
+ """Reject a choice whose `value` is blank.
190
+
191
+ A blank value would render as an unlabelled option the user can select but
192
+ whose answer reads as "no answer".
193
+
194
+ Attached to the item annotation inside `Question.choices`, not to `Choice`
195
+ itself, so `TypeAdapter(Choice)` does not apply it.
196
+
197
+ Callers must pass a parsed `Choice`. A missing `value` never reaches here —
198
+ it is a required key, so pydantic rejects it as `choices.N.value: Field
199
+ required` before the choice-level validators run. On a raw dict this would
200
+ raise `KeyError`, which is not a `ValidationError` and would halt the run.
201
+
202
+ Args:
203
+ choice: The parsed `Choice` to check.
204
+
205
+ Returns:
206
+ The same `choice`, unchanged.
207
+
208
+ Raises:
209
+ ValueError: If `value` is blank or whitespace-only.
210
+ """
211
+ if not choice["value"].strip():
212
+ msg = f"choice has a blank 'value': {choice!r}"
213
+ raise ValueError(msg)
214
+ return choice
215
+
216
+
158
217
  class Choice(TypedDict):
159
218
  """A single choice option for a multiple choice or multi-select question."""
160
219
 
@@ -173,10 +232,48 @@ class Choice(TypedDict):
173
232
  ]
174
233
 
175
234
 
235
+ def _validate_question(question: Question) -> Question:
236
+ """Apply the cross-field rules of a single question.
237
+
238
+ These are the rules no single field type can express: choice questions need
239
+ a non-empty `choices` list, and non-choice questions must not define one.
240
+
241
+ `Literal` already rejects an unknown `type` and `strict=True` a non-boolean
242
+ `required` before this runs, so they are not re-checked here.
243
+
244
+ Args:
245
+ question: The parsed `Question` to check.
246
+
247
+ Returns:
248
+ The same `question`, unchanged.
249
+
250
+ Raises:
251
+ ValueError: If the question violates one of the rules above.
252
+ """
253
+ question_type = question["type"]
254
+ question_text = question["question"]
255
+ choices = question.get("choices")
256
+ if question_type in CHOICE_QUESTION_TYPES:
257
+ if not choices:
258
+ msg = (
259
+ f"{question_type} question {question_text!r} requires a "
260
+ f"non-empty 'choices' list"
261
+ )
262
+ raise ValueError(msg)
263
+ elif choices:
264
+ msg = f"{question_type} question {question_text!r} must not define 'choices'"
265
+ raise ValueError(msg)
266
+ return question
267
+
268
+
176
269
  class Question(TypedDict):
177
270
  """A question to ask the user."""
178
271
 
179
- question: Annotated[str, Field(description="The question text to display.")]
272
+ question: Annotated[
273
+ str,
274
+ AfterValidator(_validate_question_text),
275
+ Field(description="The question text to display.", min_length=1),
276
+ ]
180
277
 
181
278
  type: Annotated[
182
279
  QuestionType,
@@ -196,7 +293,7 @@ class Question(TypedDict):
196
293
 
197
294
  choices: NotRequired[
198
295
  Annotated[
199
- list[Choice],
296
+ list[Annotated[Choice, AfterValidator(_validate_choice)]],
200
297
  Field(
201
298
  description=(
202
299
  "Options for 'multiple_choice' and 'multi_select' questions. "
@@ -231,14 +328,62 @@ class Question(TypedDict):
231
328
  ]
232
329
 
233
330
 
331
+ ValidatedQuestion = Annotated[Question, AfterValidator(_validate_question)]
332
+ """A `Question` with its cross-field rules applied during pydantic parsing.
333
+
334
+ Only the cross-field `choices` rules are scoped to this alias. The field-level
335
+ rules on `Question.question` and on `Question.choices` are unconditional, so
336
+ they also apply wherever `Question` itself is pydantic-parsed — notably
337
+ `TypeAdapter(AskUserRequest)` in `tui.textual_adapter`, which re-validates the
338
+ interrupt payload client-side and re-raises on failure. Keep that in mind
339
+ before adding another field-level rule here.
340
+
341
+ Where a `ValueError` from one of these validators ends up depends on the path.
342
+ On the tool path it becomes a tool-call `ValidationError`, which `ToolNode`
343
+ turns into an error `ToolMessage` the model can correct and retry from. On the
344
+ client re-validation path there is no tool call and `textual_adapter` logs and
345
+ re-raises instead."""
346
+
347
+
348
+ def _validate_questions(questions: list[ValidatedQuestion]) -> list[ValidatedQuestion]:
349
+ """Reject an empty `questions` list.
350
+
351
+ Per-question rules live on `ValidatedQuestion`; this covers the one rule
352
+ about the list itself. Attached both to the tool's `questions` parameter
353
+ and to `AskUserRequest.questions`, so the client re-validation boundary
354
+ rejects an empty list too — `AskUserMenu([])` would otherwise build a
355
+ titled prompt with no question widgets and nothing focusable.
356
+
357
+ Args:
358
+ questions: The parsed `questions` argument to check.
359
+
360
+ Returns:
361
+ The same `questions`, unchanged.
362
+
363
+ Raises:
364
+ ValueError: If the list is empty.
365
+ """
366
+ if not questions:
367
+ msg = "ask_user requires at least one question"
368
+ raise ValueError(msg)
369
+ return questions
370
+
371
+
234
372
  class AskUserRequest(TypedDict):
235
373
  """Request payload sent via interrupt when asking the user questions."""
236
374
 
237
375
  type: Literal["ask_user"]
238
376
  """Discriminator tag, always `'ask_user'`."""
239
377
 
240
- questions: list[Question]
241
- """Questions to present to the user."""
378
+ questions: Annotated[list[ValidatedQuestion], AfterValidator(_validate_questions)]
379
+ """Questions to present to the user.
380
+
381
+ `ValidatedQuestion` rather than `Question`, and carrying
382
+ `_validate_questions`, so every rule the tool applies also applies where
383
+ `tui.textual_adapter` re-validates this payload. A choice question with no
384
+ `choices` would otherwise reach the client and degrade to a text box, and
385
+ an empty list would render a prompt with no questions in it.
386
+ """
242
387
 
243
388
  tool_call_id: str
244
389
  """ID of the originating tool call, used to route the response back."""
@@ -446,9 +591,10 @@ def format_ask_user_transcript(questions: list[Question], answers: list[str]) ->
446
591
 
447
592
  Args:
448
593
  questions: Questions that were asked. Callers must pass questions whose
449
- `question` text is a non-empty string; `ask_user._validate_questions`
450
- enforces that before interrupting. The empty default below only
451
- keeps a caller that skips validation from raising `KeyError`.
594
+ `question` text is a non-empty string; `_validate_question_text`,
595
+ attached to `Question.question`, enforces that before interrupting.
596
+ The empty default below only keeps a caller that skips validation
597
+ from raising `KeyError`.
452
598
  answers: Answers, positionally matched to `questions`. A missing entry
453
599
  falls back to `ASK_USER_NO_ANSWER`; extra entries are dropped.
454
600
 
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "b650b41"
3
+ BUILD_COMMIT = "1aa14cc"
@@ -444,6 +444,19 @@ request. Also the escape hatch for hosts embedding this package that manage
444
444
  process, so an embedder that starts its own would otherwise race this one.
445
445
  """
446
446
 
447
+ READ_PROJECT_DOTENV = "DEEPAGENTS_CODE_READ_PROJECT_DOTENV"
448
+ """Toggle loading the *project* `.env` (the one found walking up from cwd).
449
+
450
+ Enabled by default, preserving the historical behavior of applying the nearest
451
+ project `.env` to the process environment (`override=False`, shell exports
452
+ win). Set to a falsy value (`0`, `false`, `no`, `off`) — or `[startup]`
453
+ `read_project_dotenv = false` in config.toml — to skip the project file
454
+ entirely, as defense-in-depth against a cloned repo whose `.env` carries
455
+ hostile values the dotenv denylist does not yet enumerate. The global
456
+ `~/.deepagents/.env` is unaffected. This is user-controlled process env, not a
457
+ repo file, so a project `.env` cannot disable itself.
458
+ """
459
+
447
460
  RECURSION_LIMIT = "DEEPAGENTS_CODE_RECURSION_LIMIT"
448
461
  """Override the main agent's LangGraph `recursion_limit` (graph step budget).
449
462
 
@@ -1,6 +1,6 @@
1
1
  r"""Runtime patches over Textual internals, imported for side effect.
2
2
 
3
- This module hosts five independent best-effort patches over private Textual
3
+ This module hosts six independent best-effort patches over private Textual
4
4
  APIs. Each guards its own import/assignment and degrades to stock Textual
5
5
  behavior (logging a warning) if the targeted internals move, so they have
6
6
  separate lifecycles — do not delete the whole file when only one lands
@@ -42,7 +42,23 @@ upstream.
42
42
  drag) to word boundaries. No upstream issue tracks this yet, so it has
43
43
  no removal criterion — it stays until Textual grows native word select.
44
44
 
45
- 4. Detached-widget hit filtering. The compositor keeps reporting a widget as
45
+ 4. Shift-click selection extension. Stock Textual replaces an existing text
46
+ selection on every mouse press, so Shift+click cannot move the active end
47
+ of a drag-selected range. The patch preserves the original selection anchor
48
+ and applies the click as its new end. No upstream issue tracks this yet.
49
+
50
+ Known terminal limitation: this only works when the terminal delivers the
51
+ modified click to the app. Ghostty binds Shift+click to its own selection
52
+ and never forwards the event while mouse reporting is active, so
53
+ Shift+click is a no-op there (users can `keybind = shift+click=unbind` to
54
+ opt out). iTerm2, kitty, and WezTerm forward it with the shift modifier
55
+ bit set, which is what the patch keys on. If Shift+click "does nothing"
56
+ for a user, check terminal delivery first — e.g. run
57
+ `printf '\e[?1003h\e[?1006h'; cat -v` and confirm Shift+click prints a
58
+ `^[[<;...;4M`-style sequence (the `4` is the shift bit) — before digging
59
+ into this patch.
60
+
61
+ 5. Detached-widget hit filtering. The compositor keeps reporting a widget as
46
62
  visible for a few event-loop iterations after it leaves the DOM, which
47
63
  `Markdown.update` (and therefore the `MarkdownStream` that drives every
48
64
  streaming assistant message) does constantly. `Screen._forward_event`
@@ -51,7 +67,7 @@ upstream.
51
67
  crashes the app with `AttributeError: 'NoneType' object has no attribute
52
68
  'region'`. Tracked in Textualize/textual#6643; remove when that lands.
53
69
 
54
- 5. Diff-gutter exclusion from selections. Textual paints the selection
70
+ 6. Diff-gutter exclusion from selections. Textual paints the selection
55
71
  highlight from the geometry stored in `Screen.selections`, so excluding
56
72
  a diff row's decorative gutter (line number, `+`/`-` marker) only in
57
73
  `Widget.get_selection` would copy the right text while still highlighting
@@ -447,6 +463,97 @@ else:
447
463
  )
448
464
 
449
465
 
466
+ try:
467
+ from textual import events as _shift_events
468
+ from textual.screen import Screen as _ShiftScreen
469
+ from textual.selection import SelectEnd, SelectStart, SelectState
470
+
471
+ _original_forward_event_with_shift = _ShiftScreen._forward_event
472
+ except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
473
+ logger.warning(
474
+ "Textual Shift+click selection patch skipped (textual %s): %s",
475
+ _textual_version,
476
+ exc,
477
+ )
478
+ else:
479
+
480
+ def _shift_click_anchor(screen: Screen, event: Event) -> SelectState | None:
481
+ # When this returns None the press falls through to stock Textual,
482
+ # which starts a fresh selection — indistinguishable from the event
483
+ # never arriving. Before debugging the branches below, confirm the
484
+ # terminal forwarded a shift-modified click at all (see the module
485
+ # docstring's patch 4 note); terminals like Ghostty consume Shift+click
486
+ # locally, so `event.shift` never becomes True here.
487
+ if (
488
+ not isinstance(event, _shift_events.MouseDown)
489
+ or not event.shift
490
+ or screen.app.mouse_captured
491
+ or not screen.selections
492
+ ):
493
+ return None
494
+ select_state = screen._select_state
495
+ if select_state is None or select_state.end is None:
496
+ return None
497
+ content_widget = select_state.start.content_widget
498
+ if content_widget is not None and not content_widget.is_attached:
499
+ return None
500
+ return select_state if select_state.is_attached_to_dom() else None
501
+
502
+ def _rebase_anchor_scroll(anchor_start: SelectStart) -> SelectStart:
503
+ # `SelectStart.pointer_start_offset` adds the scroll travelled since
504
+ # the drag began, which tracks the viewport rather than the anchored
505
+ # text. That is harmless mid-drag, but a Shift+click can arrive many
506
+ # rows after the container scrolled — the transcript auto-scrolls while
507
+ # a message streams — leaving the anchor pointing at whatever text now
508
+ # occupies its old screen row. Fold the drift into the pointer delta
509
+ # and re-base against the current scroll offset, so the anchor stays on
510
+ # its original text.
511
+ container = anchor_start.container
512
+ drift = container.scroll_offset - anchor_start.container_initial_scroll_offset
513
+ return SelectStart(
514
+ container,
515
+ anchor_start.container_pointer_delta - drift,
516
+ anchor_start.container_initial_offset,
517
+ container.scroll_offset,
518
+ content_widget=anchor_start.content_widget,
519
+ content_offset=anchor_start.content_offset,
520
+ )
521
+
522
+ def _extend_selection_to_click(
523
+ screen: Screen,
524
+ anchor: SelectState | None,
525
+ event: _shift_events.MouseDown,
526
+ ) -> None:
527
+ click_state = screen._select_state
528
+ if anchor is None or click_state is None:
529
+ return
530
+ click = click_state.start
531
+ # Stock Textual clears the selection when a MouseUp lands on the
532
+ # offset of its MouseDown. Forget the offset so the Shift+click's own
533
+ # MouseUp leaves the extension we install below alone.
534
+ screen._mouse_down_offset = None
535
+ screen._select_state = SelectState(
536
+ event.screen_offset,
537
+ _rebase_anchor_scroll(anchor.start),
538
+ SelectEnd(click.container, click.content_widget, click.content_offset),
539
+ )
540
+
541
+ def _forward_event_with_shift_select(self: Screen, event: Event) -> None:
542
+ shift_anchor = _shift_click_anchor(self, event)
543
+ _original_forward_event_with_shift(self, event)
544
+ if isinstance(event, _shift_events.MouseDown):
545
+ _extend_selection_to_click(self, shift_anchor, event)
546
+
547
+ try:
548
+ _ShiftScreen._forward_event = _forward_event_with_shift_select # ty: ignore[invalid-assignment]
549
+ except (AttributeError, TypeError) as exc: # pragma: no cover - defensive
550
+ logger.warning(
551
+ "Textual Shift+click selection patch assignment rejected (textual %s): %s",
552
+ _textual_version,
553
+ exc,
554
+ )
555
+
556
+
450
557
  try:
451
558
  from textual.screen import Screen as _HitScreen
452
559
 
@@ -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.59" # x-release-please-version
5
+ __version__ = "0.1.60" # 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."""
@@ -48,7 +48,6 @@ if TYPE_CHECKING:
48
48
  from langchain.agents.middleware import (
49
49
  HumanInTheLoopMiddleware,
50
50
  InterruptOnConfig,
51
- ToolErrorMiddleware,
52
51
  )
53
52
  from langchain.agents.middleware.types import AgentMiddleware, ToolCallRequest
54
53
  from langchain.tools import (
@@ -70,7 +69,6 @@ from deepagents_code._repository_bounds import (
70
69
  REPOSITORY_TOOL_NAMES,
71
70
  RepositoryBounds,
72
71
  )
73
- from deepagents_code._tool_errors import ToolArgumentError
74
72
  from deepagents_code.approval_mode import (
75
73
  ApprovalMode,
76
74
  aread_approval_mode_from_store,
@@ -178,47 +176,6 @@ def _get_harness_tool_descriptions(
178
176
  return dict(_harness_profile_for_model(model, None).tool_description_overrides)
179
177
 
180
178
 
181
- # Tools that raise `ToolArgumentError` on model-authored arguments. The name
182
- # filter is a second gate only: recovery keys off the exception type, so a
183
- # different error from one of these tools still halts the run.
184
- #
185
- # `read_file` is deliberately absent. It catches its own argument errors and
186
- # returns an error `ToolMessage` already. The only `ValueError`s that escape it
187
- # come from backend invariants the model cannot fix, and the SDK raises those
188
- # on purpose to stop a backend from silently skipping unshown source lines.
189
- _TOOL_ARG_VALIDATION_TOOLS: tuple[str, ...] = ("ask_user",)
190
-
191
-
192
- def _tool_arg_validation_on_error(
193
- exc: Exception, request: ToolCallRequest
194
- ) -> str | None:
195
- """Convert a `ToolArgumentError` into a model-correctable message.
196
-
197
- `ToolErrorMiddleware` re-raises `GraphBubbleUp` before it calls this, so
198
- interrupts and parent commands never arrive here.
199
-
200
- Args:
201
- exc: Exception raised during tool execution.
202
- request: The tool call request that failed.
203
-
204
- Returns:
205
- A message naming the tool and the validation detail, so the model can
206
- fix its input and retry. `None` for any other exception, so
207
- unexpected errors propagate and halt the run.
208
- """
209
- if isinstance(exc, ToolArgumentError):
210
- # The run no longer fails, so this is the only record that the model
211
- # sent bad arguments. `exc_info` keeps the raise site for debugging.
212
- logger.warning(
213
- "Recovered tool argument error from %s: %s",
214
- request.tool_call["name"],
215
- exc,
216
- exc_info=exc,
217
- )
218
- return f"`{request.tool_call['name']}` failed: {exc}. Fix the input and retry."
219
- return None
220
-
221
-
222
179
  def _inject_fs_tools_into_subagents(
223
180
  custom_subagents: list[SubAgent | CompiledSubAgent],
224
181
  *,
@@ -2554,9 +2511,6 @@ def create_cli_agent(
2554
2511
  from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
2555
2512
 
2556
2513
  hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
2557
- # No `ToolErrorMiddleware` here. `_TOOL_ARG_VALIDATION_TOOLS` covers
2558
- # `ask_user` only, and subagents never get `AskUserMiddleware`, so an
2559
- # instance on this stack could never fire.
2560
2514
  middleware.append(
2561
2515
  ServerHooksMiddleware(
2562
2516
  cwd=hooks_cwd,
@@ -3130,20 +3084,6 @@ def create_cli_agent(
3130
3084
  rubric_kwargs["max_iterations"] = rubric_max_iterations
3131
3085
  agent_middleware.append(ReliableRubricMiddleware(**rubric_kwargs))
3132
3086
 
3133
- # Turn a `ToolArgumentError` into a recoverable error `ToolMessage` instead
3134
- # of a fatal run error. Any other exception propagates and halts the run.
3135
- #
3136
- # This must stay last. `_chain_tool_call_wrappers` composes the list first
3137
- # to outermost, so anything appended after this would run inside the
3138
- # handler. `ServerHooksMiddleware` keeps a plain `ValueError` fatal on
3139
- # purpose: it means the client answered a different request. Catching that
3140
- # here would report a hook fault to the model as its own bad tool input.
3141
- agent_middleware.append(
3142
- ToolErrorMiddleware(
3143
- _tool_arg_validation_on_error, tools=list(_TOOL_ARG_VALIDATION_TOOLS)
3144
- )
3145
- )
3146
-
3147
3087
  # Create the agent
3148
3088
  all_subagents: list[SubAgent | CompiledSubAgent | AsyncSubAgent] = [
3149
3089
  *custom_subagents,