deepagents-code 0.1.56__tar.gz → 0.1.57__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 (484) hide show
  1. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/AGENTS.md +1 -0
  2. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/CHANGELOG.md +22 -0
  3. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/PKG-INFO +2 -2
  4. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/THREAT_MODEL.md +3 -2
  5. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_ask_user_types.py +105 -8
  6. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_build_info.py +1 -1
  7. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_dep_floor_check.py +227 -34
  8. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_env_vars.py +33 -0
  9. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_session_stats.py +45 -0
  10. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_textual_patches.py +7 -0
  11. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_version.py +1 -1
  12. deepagents_code-0.1.57/deepagents_code/acp.py +139 -0
  13. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/agent.py +8 -5
  14. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/app.py +2496 -707
  15. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/app.tcss +41 -5
  16. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/ask_user.py +90 -13
  17. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auto_mode.py +95 -16
  18. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/extras.py +4 -8
  19. deepagents_code-0.1.57/deepagents_code/cold_cache.py +1057 -0
  20. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/config.py +7 -4
  21. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/config_manifest.py +49 -1
  22. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/configurable_model.py +251 -10
  23. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/cost_tracking.py +5 -2
  24. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/doctor.py +12 -14
  25. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/domain.py +1 -0
  26. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/wire.py +1 -0
  27. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/projection.py +3 -0
  28. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/main.py +180 -62
  29. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/model_config.py +125 -7
  30. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/resume_state.py +25 -0
  31. deepagents_code-0.1.57/deepagents_code/tui/modals/cold_cache.py +361 -0
  32. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/__init__.py +300 -31
  33. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/models.py +17 -0
  34. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +20 -0
  35. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/state.py +8 -1
  36. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/textual_adapter.py +2 -2
  37. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_paste_textarea.py +37 -0
  38. deepagents_code-0.1.57/deepagents_code/tui/widgets/ask_user.py +1312 -0
  39. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/chat_input.py +633 -17
  40. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/message_store.py +119 -31
  41. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/messages.py +200 -2
  42. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/model_selector.py +26 -13
  43. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_settings.py +2 -0
  44. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/startup_tip.py +1 -0
  45. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/subagent_panel.py +29 -23
  46. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/thread_selector.py +53 -16
  47. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/welcome.py +17 -1
  48. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/ui.py +5 -3
  49. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/update_check.py +150 -15
  50. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/pyproject.toml +2 -2
  51. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/conftest.py +32 -0
  52. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_engine.py +13 -0
  53. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_plugins_p0.py +75 -0
  54. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +2 -1
  55. deepagents_code-0.1.57/tests/unit_tests/test_acp.py +56 -0
  56. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_agent.py +3 -3
  57. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_app.py +3599 -65
  58. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ask_user_middleware.py +164 -0
  59. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auto_mode.py +620 -8
  60. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_charset.py +16 -26
  61. deepagents_code-0.1.57/tests/unit_tests/test_cold_cache.py +1287 -0
  62. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_compact_tool.py +36 -11
  63. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config_manifest.py +35 -1
  64. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_configurable_model.py +253 -4
  65. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug_console.py +68 -10
  66. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_dep_floor_check.py +309 -0
  67. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_doctor.py +6 -0
  68. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_end_to_end.py +30 -12
  69. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main.py +351 -38
  70. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main_acp_mode.py +88 -3
  71. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main_args.py +4 -4
  72. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_managed_tools.py +17 -7
  73. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_model_config.py +111 -0
  74. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_offload.py +431 -10
  75. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reload.py +597 -84
  76. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_resume_state.py +52 -13
  77. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_session_stats.py +43 -0
  78. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_threads_resume.py +34 -3
  79. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_transcript_virtualization.py +18 -2
  80. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_update_check.py +314 -15
  81. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_version.py +287 -10
  82. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +389 -0
  83. deepagents_code-0.1.57/tests/unit_tests/tui/modals/test_cold_cache.py +257 -0
  84. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/test_textual_adapter.py +17 -0
  85. deepagents_code-0.1.57/tests/unit_tests/tui/widgets/test_ask_user.py +2892 -0
  86. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_chat_input.py +644 -3
  87. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_inline_prompt.py +42 -0
  88. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_message_store.py +128 -19
  89. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_messages.py +5 -2
  90. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_model_selector.py +9 -4
  91. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_settings.py +5 -0
  92. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_startup_tip.py +4 -0
  93. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_subagent_panel.py +46 -4
  94. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_thread_selector.py +332 -74
  95. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_welcome.py +23 -0
  96. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/uv.lock +5 -5
  97. deepagents_code-0.1.56/deepagents_code/tui/widgets/ask_user.py +0 -542
  98. deepagents_code-0.1.56/deepagents_code/tui/widgets/plugin_reload.py +0 -96
  99. deepagents_code-0.1.56/tests/unit_tests/tui/widgets/test_ask_user.py +0 -1432
  100. deepagents_code-0.1.56/tests/unit_tests/tui/widgets/test_plugin_reload.py +0 -61
  101. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/.gitignore +0 -0
  102. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/ARCHITECTURE.md +0 -0
  103. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/COMMANDS.md +0 -0
  104. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/DEVELOPMENT.md +0 -0
  105. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/HOOKS.md +0 -0
  106. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/LICENSE +0 -0
  107. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/Makefile +0 -0
  108. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/PRICING.md +0 -0
  109. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/README.md +0 -0
  110. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/__init__.py +0 -0
  111. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/__main__.py +0 -0
  112. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_cli_context.py +0 -0
  113. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_constants.py +0 -0
  114. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_debug.py +0 -0
  115. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_debug_buffer.py +0 -0
  116. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_fake_models.py +0 -0
  117. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_git.py +0 -0
  118. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_glm_5p2_profile.py +0 -0
  119. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_invocation.py +0 -0
  120. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_markdown.py +0 -0
  121. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_paths.py +0 -0
  122. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_repository_bounds.py +0 -0
  123. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_server_config.py +0 -0
  124. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_startup_error.py +0 -0
  125. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_testing_models.py +0 -0
  126. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_tool_stream.py +0 -0
  127. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/approval_mode.py +0 -0
  128. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auth_display.py +0 -0
  129. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auth_store.py +0 -0
  130. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/__init__.py +0 -0
  131. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
  132. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
  133. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  134. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  135. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  136. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  137. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/bundled_prices.README.md +0 -0
  138. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/bundled_prices.json +0 -0
  139. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/__init__.py +0 -0
  140. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/__init__.py +0 -0
  141. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/auth.py +0 -0
  142. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/config.py +0 -0
  143. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/mcp.py +0 -0
  144. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/tools.py +0 -0
  145. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/__init__.py +0 -0
  146. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/server.py +0 -0
  147. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/server_manager.py +0 -0
  148. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/non_interactive.py +0 -0
  149. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/remote_client.py +0 -0
  150. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/clipboard.py +0 -0
  151. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/command_registry.py +0 -0
  152. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/default_agent_prompt.md +0 -0
  153. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/diff_utils.py +0 -0
  154. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/editor.py +0 -0
  155. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/event_bus.py +0 -0
  156. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/extras_info.py +0 -0
  157. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/file_ops.py +0 -0
  158. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/formatting.py +0 -0
  159. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_rubric.py +0 -0
  160. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_state_notice.py +0 -0
  161. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_tools.py +0 -0
  162. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/__init__.py +0 -0
  163. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/capabilities.py +0 -0
  164. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/client.py +0 -0
  165. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/client_lifecycle.py +0 -0
  166. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/context.py +0 -0
  167. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/engine.py +0 -0
  168. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/env.py +0 -0
  169. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/envelope.py +0 -0
  170. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/interrupt.py +0 -0
  171. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/legacy.py +0 -0
  172. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/loading.py +0 -0
  173. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/manager.py +0 -0
  174. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/migration.py +0 -0
  175. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/__init__.py +0 -0
  176. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/adapters.py +0 -0
  177. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/config.py +0 -0
  178. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/transport.py +0 -0
  179. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/permissions.py +0 -0
  180. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/presenter.py +0 -0
  181. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/reducer.py +0 -0
  182. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/runner.py +0 -0
  183. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/runtime.py +0 -0
  184. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/server_middleware.py +0 -0
  185. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/snapshot.py +0 -0
  186. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/tools.py +0 -0
  187. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/transcript.py +0 -0
  188. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/trust.py +0 -0
  189. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
  190. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/input.py +0 -0
  191. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/__init__.py +0 -0
  192. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/openai_codex.py +0 -0
  193. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_config.py +0 -0
  194. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_factory.py +0 -0
  195. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_provider.py +0 -0
  196. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_registry.py +0 -0
  197. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/iterm_cursor_guide.py +0 -0
  198. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/json_types.py +0 -0
  199. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/local_context.py +0 -0
  200. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/managed_tools.py +0 -0
  201. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_auth.py +0 -0
  202. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_config.py +0 -0
  203. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_disabled.py +0 -0
  204. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_login_service.py +0 -0
  205. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_oauth_ui.py +0 -0
  206. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/__init__.py +0 -0
  207. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/_registry.py +0 -0
  208. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/base.py +0 -0
  209. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/github.py +0 -0
  210. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/slack.py +0 -0
  211. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_tools.py +0 -0
  212. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/media_utils.py +0 -0
  213. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/memory_guard.py +0 -0
  214. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/notifications.py +0 -0
  215. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/offload.py +0 -0
  216. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/offload_middleware.py +0 -0
  217. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/onboarding.py +0 -0
  218. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/output.py +0 -0
  219. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/paste_collapse.py +0 -0
  220. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/__init__.py +0 -0
  221. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/_json.py +0 -0
  222. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/__init__.py +0 -0
  223. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/hooks.py +0 -0
  224. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/mcp.py +0 -0
  225. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/skills.py +0 -0
  226. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
  227. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/commands_cli.py +0 -0
  228. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/discovery.py +0 -0
  229. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/manifest.py +0 -0
  230. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/marketplace.py +0 -0
  231. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/models.py +0 -0
  232. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/store.py +0 -0
  233. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/substitution.py +0 -0
  234. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/project_utils.py +0 -0
  235. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/py.typed +0 -0
  236. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/reasoning_effort.py +0 -0
  237. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/reliable_rubric.py +0 -0
  238. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/server_graph.py +0 -0
  239. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/sessions.py +0 -0
  240. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/__init__.py +0 -0
  241. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/commands.py +0 -0
  242. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/invocation.py +0 -0
  243. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/load.py +0 -0
  244. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/merge.py +0 -0
  245. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/trust.py +0 -0
  246. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/state_migration.py +0 -0
  247. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/subagents.py +0 -0
  248. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/system_prompt.md +0 -0
  249. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/terminal_capabilities.py +0 -0
  250. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/terminal_escape.py +0 -0
  251. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/theme.py +0 -0
  252. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tool_catalog.py +0 -0
  253. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tool_display.py +0 -0
  254. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tools.py +0 -0
  255. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/__init__.py +0 -0
  256. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/__init__.py +0 -0
  257. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/content.py +0 -0
  258. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
  259. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/resume_compact.py +0 -0
  260. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/screens/__init__.py +0 -0
  261. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/__init__.py +0 -0
  262. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
  263. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
  264. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
  265. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_links.py +0 -0
  266. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/agent_selector.py +0 -0
  267. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/approval.py +0 -0
  268. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/auth.py +0 -0
  269. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/auto_mode_notice.py +0 -0
  270. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/autocomplete.py +0 -0
  271. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/codex_auth.py +0 -0
  272. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/context_usage.py +0 -0
  273. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/cwd_switch.py +0 -0
  274. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/debug_console.py +0 -0
  275. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/diff.py +0 -0
  276. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/effort_selector.py +0 -0
  277. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/goal_review.py +0 -0
  278. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/goal_status.py +0 -0
  279. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/history.py +0 -0
  280. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/install_confirm.py +0 -0
  281. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/launch_init.py +0 -0
  282. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/loading.py +0 -0
  283. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_login.py +0 -0
  284. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
  285. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_viewer.py +0 -0
  286. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_center.py +0 -0
  287. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_detail.py +0 -0
  288. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
  289. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/skill_trust.py +0 -0
  290. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/status.py +0 -0
  291. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/theme_selector.py +0 -0
  292. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
  293. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
  294. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
  295. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_available.py +0 -0
  296. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_confirm.py +0 -0
  297. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_progress.py +0 -0
  298. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
  299. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/unicode_security.py +0 -0
  300. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/arxiv-search/SKILL.md +0 -0
  301. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  302. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/langgraph-docs/SKILL.md +0 -0
  303. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/SKILL.md +0 -0
  304. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  305. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  306. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/web-research/SKILL.md +0 -0
  307. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/hatch_build.py +0 -0
  308. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/images/tui.png +0 -0
  309. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/check_imports.py +0 -0
  310. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/debug_server.sh +0 -0
  311. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/generate_commands_catalog.py +0 -0
  312. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/install.sh +0 -0
  313. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/README.md +0 -0
  314. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/__init__.py +0 -0
  315. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/__init__.py +0 -0
  316. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  317. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
  318. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  319. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/conftest.py +0 -0
  320. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_acp_mode.py +0 -0
  321. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_auto_approve_remote.py +0 -0
  322. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_compact_resume.py +0 -0
  323. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
  324. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_offload_server_side.py +0 -0
  325. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_sandbox_factory.py +0 -0
  326. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_sandbox_operations.py +0 -0
  327. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/__init__.py +0 -0
  328. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/__init__.py +0 -0
  329. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/__init__.py +0 -0
  330. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_auth.py +0 -0
  331. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_extras.py +0 -0
  332. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_mcp.py +0 -0
  333. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_tools.py +0 -0
  334. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
  335. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/__init__.py +0 -0
  336. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/models/__init__.py +0 -0
  337. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/models/test_models.py +0 -0
  338. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
  339. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_configuration.py +0 -0
  340. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_execution.py +0 -0
  341. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_manager.py +0 -0
  342. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_presenter.py +0 -0
  343. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_server_lifecycle.py +0 -0
  344. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_transcript.py +0 -0
  345. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_trust.py +0 -0
  346. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/__init__.py +0 -0
  347. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_marketplace.py +0 -0
  348. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_plugin_hooks.py +0 -0
  349. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_store.py +0 -0
  350. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/__init__.py +0 -0
  351. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_commands.py +0 -0
  352. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_load.py +0 -0
  353. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_merge.py +0 -0
  354. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_skill_trust.py +0 -0
  355. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_skills_json.py +0 -0
  356. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
  357. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/__init__.py +0 -0
  358. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/conftest.py +0 -0
  359. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
  360. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test__tool_stream.py +0 -0
  361. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_agent_friendly.py +0 -0
  362. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_approval_mode.py +0 -0
  363. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_args.py +0 -0
  364. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ask_user_types.py +0 -0
  365. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_display.py +0 -0
  366. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_store.py +0 -0
  367. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
  368. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_clipboard.py +0 -0
  369. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
  370. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_command_registry.py +0 -0
  371. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config.py +0 -0
  372. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config_recursion_limit.py +0 -0
  373. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cost_tracking.py +0 -0
  374. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cursor_blink.py +0 -0
  375. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cursor_style.py +0 -0
  376. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug.py +0 -0
  377. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug_buffer.py +0 -0
  378. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_diff_utils.py +0 -0
  379. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_editor.py +0 -0
  380. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_env_vars.py +0 -0
  381. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_event_bus.py +0 -0
  382. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_exception_handling.py +0 -0
  383. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_extras_info.py +0 -0
  384. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_file_ops.py +0 -0
  385. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_formatting.py +0 -0
  386. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_git.py +0 -0
  387. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
  388. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_criteria_client.py +0 -0
  389. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_rubric.py +0 -0
  390. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_state_notice.py +0 -0
  391. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_state_persistence.py +0 -0
  392. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_tools.py +0 -0
  393. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_hatch_build.py +0 -0
  394. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_hooks.py +0 -0
  395. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_imports.py +0 -0
  396. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_input_parsing.py +0 -0
  397. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_install_command.py +0 -0
  398. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_install_script.py +0 -0
  399. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_invocation.py +0 -0
  400. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  401. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_json_types.py +0 -0
  402. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_local_context.py +0 -0
  403. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_auth.py +0 -0
  404. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_config.py +0 -0
  405. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_disabled.py +0 -0
  406. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_login_service.py +0 -0
  407. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  408. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_tools.py +0 -0
  409. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_media_utils.py +0 -0
  410. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_memory_guard.py +0 -0
  411. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_model_switch.py +0 -0
  412. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_non_interactive.py +0 -0
  413. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_notifications.py +0 -0
  414. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_onboarding.py +0 -0
  415. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  416. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_output.py +0 -0
  417. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_paths.py +0 -0
  418. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reasoning_effort.py +0 -0
  419. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reliable_rubric.py +0 -0
  420. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_remote_client.py +0 -0
  421. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_repository_bounds.py +0 -0
  422. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_rubric_cli.py +0 -0
  423. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_config.py +0 -0
  424. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_factory.py +0 -0
  425. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_provider.py +0 -0
  426. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_registry.py +0 -0
  427. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server.py +0 -0
  428. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_config.py +0 -0
  429. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_graph.py +0 -0
  430. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_helpers.py +0 -0
  431. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_manager.py +0 -0
  432. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sessions.py +0 -0
  433. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_shell_allow_list.py +0 -0
  434. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_skill_invocation.py +0 -0
  435. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_startup_blocking.py +0 -0
  436. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  437. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_state_migration.py +0 -0
  438. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_subagents.py +0 -0
  439. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  440. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_escape.py +0 -0
  441. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  442. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_textual_patches.py +0 -0
  443. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_theme.py +0 -0
  444. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tool_catalog.py +0 -0
  445. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tool_display.py +0 -0
  446. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tracing_replicas.py +0 -0
  447. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ui.py +0 -0
  448. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_unicode_security.py +0 -0
  449. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/__init__.py +0 -0
  450. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_current_thread.py +0 -0
  451. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  452. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
  453. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/__init__.py +0 -0
  454. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/__init__.py +0 -0
  455. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
  456. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
  457. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/__init__.py +0 -0
  458. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_agent_selector.py +0 -0
  459. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_approval.py +0 -0
  460. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_auth_widgets.py +0 -0
  461. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +0 -0
  462. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
  463. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
  464. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
  465. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
  466. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
  467. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_history.py +0 -0
  468. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
  469. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
  470. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_links.py +0 -0
  471. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
  472. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
  473. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
  474. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +0 -0
  475. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_center.py +0 -0
  476. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
  477. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
  478. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
  479. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_status.py +0 -0
  480. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
  481. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
  482. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
  483. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
  484. {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
@@ -78,6 +78,7 @@ Apply these rules to new UI; do not treat them as a mandate to refactor existing
78
78
  - Use `textual.pilot` for async UI testing - see [Testing guide](https://textual.textualize.io/guide/testing/)
79
79
  - Snapshot testing available for visual regression - see repo `notes/snapshot_testing.md`
80
80
  - For modal flows, test the real interaction path with keypresses when possible. Unit tests that call action methods or resume handlers directly can miss focus and modal-stack bugs.
81
+ - A modal test that pushes the screen onto a bare `App` host cannot catch app-level key interception. The app owns a priority `shift+tab -> toggle_auto_approve` binding (`app.py`) that wins dispatch over any screen binding; `action_toggle_auto_approve` routes the key to the active screen. Cursor-style modals (highlighted rows, no focusable children) just implement `action_move_up` — the router's `_SupportsReverseNav` protocol branch picks them up automatically. The protocol matches on method *presence*, so enrollment is opt-out, not opt-in: a screen that defines `action_move_up` for its own arrow keys gets `shift+tab` reverse-nav whether or not it was written with that key in mind. Screens needing different behavior (`focus_previous`, tab bars) — or none — need an explicit branch *above* the protocol check in `action_toggle_auto_approve`. Either way, add an app-level regression test in `test_app.py` that presses `shift+tab` through the real `DeepAgentsApp` dispatch, or the modal will silently swallow the key.
81
82
  - Do not open another modal or refocus the base chat input directly inside a modal dismiss callback. Preserve the non-blocking `push_screen(..., callback)` flow and schedule follow-up UI work with `call_after_refresh` so the dismissing modal fully unwinds first.
82
83
  - Be cautious replacing `push_screen(..., callback)` with an awaited modal result inside slash-command handlers; awaiting can block the Textual message pump and break keyboard navigation in the active modal. Slash commands are dispatched from `on_chat_input_submitted`, which is awaited inline on that pump, so a modal awaited anywhere in the call chain never receives the keys that would resolve it and looks frozen.
83
84
  - When a command genuinely needs an awaited modal result, hand the continuation to `_schedule_off_message_pump` so the handler returns first. A detached continuation runs outside the handler's `try/except` and is cancelled at app exit, so it must catch its own exceptions and mount its own failure message — otherwise the failure reaches only `_log_task_exception` and the user sees no outcome at all — and it must tolerate cancellation part-way through, including mid-subprocess. Anything that mutates the running tool environment must also take `_environment_mutation_lock`, since the handler no longer serializes commands by blocking.
@@ -2,6 +2,28 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.57](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.56...deepagents-code==0.1.57) (2026-08-18)
6
+
7
+ ### Features
8
+
9
+ - Added warnings before expensive cold-cache turns and trust user-declared endpoints for cold-cache policies ([#5439](https://github.com/langchain-ai/deepagents/issues/5439), [#5462](https://github.com/langchain-ai/deepagents/issues/5462)).
10
+ - Made the chat input resizable by dragging its top border ([#5524](https://github.com/langchain-ai/deepagents/issues/5524)).
11
+ - Added a `multi_select` question type to `ask_user` ([#5097](https://github.com/langchain-ai/deepagents/issues/5097)).
12
+ - Added support for ACP approval modes ([#5394](https://github.com/langchain-ai/deepagents/issues/5394)).
13
+ - Added `DeepSeek-V4-Pro-0813` to the model picker ([#5512](https://github.com/langchain-ai/deepagents/issues/5512)).
14
+ - Show conversation turns alongside message counts ([#5571](https://github.com/langchain-ai/deepagents/issues/5571)).
15
+ - Include `TERM_PROGRAM` in the resume hint ([#5548](https://github.com/langchain-ai/deepagents/issues/5548)).
16
+
17
+ ### Bug Fixes
18
+
19
+ - Report total context after `/offload` ([#5488](https://github.com/langchain-ai/deepagents/issues/5488)).
20
+ - Fixed transcript and thread restoration issues, including hydration lag, scrolling resumed threads to the bottom, and hiding empty previous-thread hints ([#5479](https://github.com/langchain-ai/deepagents/issues/5479), [#5543](https://github.com/langchain-ai/deepagents/issues/5543), [#5552](https://github.com/langchain-ai/deepagents/issues/5552)).
21
+ - Fixed Auto-mode approval handling by binding “yes” to the paired `ask_user` question and avoiding duplicate Auto denial notices ([#5038](https://github.com/langchain-ai/deepagents/issues/5038), [#5501](https://github.com/langchain-ai/deepagents/issues/5501)).
22
+ - Improved reload behavior by keeping the chat input responsive during `/reload`, reporting MCP server changes, and avoiding plugin reload prompt flashes or startup hints ([#5529](https://github.com/langchain-ai/deepagents/issues/5529), [#5504](https://github.com/langchain-ai/deepagents/issues/5504), [#5500](https://github.com/langchain-ai/deepagents/issues/5500), [#5502](https://github.com/langchain-ai/deepagents/issues/5502)).
23
+ - Improved dependency update UI by preserving editable fields and hiding dependency details after updates ([#5521](https://github.com/langchain-ai/deepagents/issues/5521), [#5519](https://github.com/langchain-ai/deepagents/issues/5519)).
24
+ - Fixed chat UI polish issues, including detached spacer mount anchors, the unfocused input cursor, and relative timestamp toggle display ([#5516](https://github.com/langchain-ai/deepagents/issues/5516), [#5258](https://github.com/langchain-ai/deepagents/issues/5258), [#5503](https://github.com/langchain-ai/deepagents/issues/5503)).
25
+ - Refresh the splash version after updates ([#5520](https://github.com/langchain-ai/deepagents/issues/5520)).
26
+
5
27
  ## [0.1.56](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.55...deepagents-code==0.1.56) (2026-08-14)
6
28
 
7
29
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: deepagents-code
3
- Version: 0.1.56
3
+ Version: 0.1.57
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://docs.langchain.com/oss/python/deepagents/overview
6
6
  Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
@@ -31,7 +31,7 @@ Requires-Dist: anyio<5.0.0,>=4.14.2
31
31
  Requires-Dist: deepagents-acp<1.0.0,>=0.0.10
32
32
  Requires-Dist: deepagents==0.7.6
33
33
  Requires-Dist: filelock<3.30,>=3.29.7
34
- Requires-Dist: genai-prices<0.2.0,>=0.1.1
34
+ Requires-Dist: genai-prices<0.2.0,>=0.1.3
35
35
  Requires-Dist: httpx<1.0.0,>=0.28.1
36
36
  Requires-Dist: langchain-anthropic<2.0.0,>=1.5.6
37
37
  Requires-Dist: langchain-google-genai<5.0.0,>=4.3.3
@@ -442,7 +442,7 @@
442
442
  #### T14: Weaker Auto Classifier Model Weakens Action Review
443
443
 
444
444
  - **Flow**: DF7 (LLM tool call) → Auto classifier review → C4 Tools
445
- - **Description**: In Auto approval mode, gated tool calls that deterministic policy cannot clear are reviewed by an LLM authorization classifier. That classifier can be pointed at a separate model (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, or `/auto model`) so reviews are cheaper and faster than the main agent model. Review quality then follows the chosen model: a weaker one is likelier to mis-authorize an action, and likelier to be steered by injected instructions in the untrusted material it reads (tool arguments, paths, prior tool output, remote metadata). Choosing the classifier is a user-level decision, so it is restricted to trusted surfaces: shell exports, the global `~/.deepagents/.env`, `~/.deepagents/config.toml`, the CLI flag, and `/auto model`. A *project* `.env` travels with a cloned repo, so `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is listed in `config._PROJECT_DOTENV_DENIED_ENV_KEYS` — the same mitigation TB4 applies to the project-MCP trust vars; without that entry a checked-in `.env` could silently downgrade the review on `dcode` startup. With it, this is a self-inflicted weakening of a control rather than an external attack path. Auto's model-independent guards are unchanged by the setting: deterministic allow/deny, the consecutive/total denial counters, batch-replay detection, control-state availability, and the human-fallback thresholds. A classifier model that cannot be constructed (bad spec, missing credentials, uninstalled provider package) never falls back to the main model — the first such batch is marked `classifier_unavailable`, so those calls are denied and do not execute, and the failing spec is latched so every subsequent batch escalates straight to human approval until a review succeeds. A transient failure instead escalates once `_CONSECUTIVE_UNAVAILABLE_FALLBACK` consecutive batches have failed, or immediately when Auto's control state cannot be persisted. The review deadline is tunable through a subset of the same trusted surfaces — shell exports, the global `~/.deepagents/.env`, and `[models].auto_classifier_timeout` in `~/.deepagents/config.toml` (there is no CLI flag and no `/auto` subcommand for it) — and `DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT` is denied from a project `.env` for the same reason, so a cloned repo cannot stall gated batches or squeeze the budget until reviews time out. `config_manifest.resolve_auto_classifier_timeout` rejects any resolved value outside `[AUTO_CLASSIFIER_TIMEOUT_FLOOR, AUTO_CLASSIFIER_TIMEOUT_CEILING]` — out-of-range and malformed values are discarded in favor of the next config source rather than clamped — so the deadline itself cannot be removed; a timed-out batch remains fail-closed (`classifier_unavailable`).
445
+ - **Description**: In Auto approval mode, gated tool calls that deterministic policy cannot clear are reviewed by an LLM authorization classifier. That classifier can be pointed at a separate model (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, or `/auto model`) so reviews are cheaper and faster than the main agent model. Review quality then follows the chosen model: a weaker one is likelier to mis-authorize an action, and likelier to be steered by injected instructions in the untrusted material it reads (tool arguments, paths, prior tool output, remote metadata, and the model-authored `ask_user` question text paired with a same-turn answer). Question text is a distinct case: the `ask_user` receipt attests only that this exact text was displayed to the user and answered, never that its content is true, so a question asserting prior or blanket authorization is untrusted content rather than evidence. `_CLASSIFIER_POLICY` instructs the classifier to read a paired question strictly as a description of a proposed action and target, to disregard directives embedded in it, and to allow an action only where that description matches the action's canonical arguments. Choosing the classifier is a user-level decision, so it is restricted to trusted surfaces: shell exports, the global `~/.deepagents/.env`, `~/.deepagents/config.toml`, the CLI flag, and `/auto model`. A *project* `.env` travels with a cloned repo, so `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is listed in `config._PROJECT_DOTENV_DENIED_ENV_KEYS` — the same mitigation TB4 applies to the project-MCP trust vars; without that entry a checked-in `.env` could silently downgrade the review on `dcode` startup. With it, this is a self-inflicted weakening of a control rather than an external attack path. Auto's model-independent guards are unchanged by the setting: deterministic allow (the deterministic deny rules are narrow and do not cover the Deny categories, so an action the classifier affirmatively allows is not re-checked downstream), the consecutive/total denial counters, batch-replay detection, control-state availability, and the human-fallback thresholds. A classifier model that cannot be constructed (bad spec, missing credentials, uninstalled provider package) never falls back to the main model — the first such batch is marked `classifier_unavailable`, so those calls are denied and do not execute, and the failing spec is latched so every subsequent batch escalates straight to human approval until a review succeeds. A transient failure instead escalates once `_CONSECUTIVE_UNAVAILABLE_FALLBACK` consecutive batches have failed, or immediately when Auto's control state cannot be persisted. The review deadline is tunable through a subset of the same trusted surfaces — shell exports, the global `~/.deepagents/.env`, and `[models].auto_classifier_timeout` in `~/.deepagents/config.toml` (there is no CLI flag and no `/auto` subcommand for it) — and `DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT` is denied from a project `.env` for the same reason, so a cloned repo cannot stall gated batches or squeeze the budget until reviews time out. `config_manifest.resolve_auto_classifier_timeout` rejects any resolved value outside `[AUTO_CLASSIFIER_TIMEOUT_FLOOR, AUTO_CLASSIFIER_TIMEOUT_CEILING]` — out-of-range and malformed values are discarded in favor of the next config source rather than clamped — so the deadline itself cannot be removed; a timed-out batch remains fail-closed (`classifier_unavailable`).
446
446
  - **Preconditions**: (1) Auto approval mode is active (interactive TUI only, and not under a sandbox); (2) a classifier model is configured through one of the trusted surfaces above — the default reuses the main agent model; (3) for the injected-review variant, untrusted content reaches the classifier through DF8/DF9 and the chosen model follows it. The intended control is that the human remains the fallback for anything the classifier does not affirmatively allow.
447
447
 
448
448
  ---
@@ -452,7 +452,7 @@
452
452
  | Input Source | Data Flows | Threats | Validation Points | Responsibility | Gaps |
453
453
  |-----------------------|-----------------------|---------------|----------------------------------------------------------------------------|----------------|----------------------------------------------------------------------------------------------|
454
454
  | User direct input | DF1, DF2 | None (TB1) | None — prompts accepted verbatim | User | No content filtering — intentional; HITL gates downstream tool calls |
455
- | 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 and prior output (T14) |
455
+ | 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) |
456
456
  | Tool/function results | DF9, DF11 | T1 | Unicode warning on URL args; `markdownify` HTML conversion | Shared | Tool *results* pass to context without prompt-injection scan |
457
457
  | 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 |
458
458
  | 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) |
@@ -521,3 +521,4 @@ Threats that appear valid in isolation but fall outside project responsibility b
521
521
  | 2026-07-28 | manual update | Extended the out-of-scope hooks row for plugin-contributed hooks: enabled plugins may supply `hooks/hooks.json`, gated by install plus enablement rather than workspace trust, with each handler's environment overlaid only by its own plugin path variables |
522
522
  | 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 |
523
523
  | 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 |
524
+ | 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 |
@@ -11,16 +11,87 @@ side produces it and which reads it.
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
- from typing import Annotated, Literal, NotRequired
14
+ from typing import Annotated, Literal, NotRequired, assert_never, get_args
15
15
 
16
16
  from pydantic import Field
17
17
  from typing_extensions import TypedDict
18
18
 
19
+ QuestionType = Literal["text", "multiple_choice", "multi_select"]
20
+ """Supported `ask_user` question types."""
21
+
22
+ QUESTION_TYPES: frozenset[str] = frozenset(get_args(QuestionType))
23
+ """Runtime membership view of `QuestionType`.
24
+
25
+ Derived via `get_args` so the membership checks in `ask_user` and `auto_mode`
26
+ cannot drift from the alias when a new question type is added. That drift would
27
+ be silent: an unrecognized type makes `_ask_user_question_count` return `None`,
28
+ which drops the user's answers as same-turn authorization without any error.
29
+ """
30
+
31
+
32
+ def _requires_choices(question_type: QuestionType) -> bool:
33
+ """Return whether `question_type` needs a non-empty `choices` list.
34
+
35
+ Args:
36
+ question_type: A member of `QuestionType`.
37
+
38
+ Returns:
39
+ True if questions of this type must define `choices`.
40
+ """
41
+ if question_type == "text":
42
+ return False
43
+ if question_type in {"multiple_choice", "multi_select"}:
44
+ return True
45
+ # Exhaustiveness guard: adding a `QuestionType` member without deciding here
46
+ # whether it needs choices fails type checking rather than silently landing
47
+ # on the wrong side of `CHOICE_QUESTION_TYPES`.
48
+ assert_never(question_type)
49
+
50
+
51
+ CHOICE_QUESTION_TYPES: frozenset[str] = frozenset(
52
+ question_type
53
+ for question_type in get_args(QuestionType)
54
+ if _requires_choices(question_type)
55
+ )
56
+ """Question types that require a non-empty `choices` list.
57
+
58
+ Derived from `_requires_choices` rather than written out, so it cannot omit a
59
+ new choice-based `QuestionType` member. Note that requiring `choices` is not the
60
+ same as being *rendered* as a choice list: the TUI has its own exhaustive
61
+ dispatch in `_QuestionWidget.compose`.
62
+ """
63
+
64
+ MULTI_SELECT_ANSWER_SEPARATOR = ", "
65
+ """Separator joining the selected values of a `multi_select` answer."""
66
+
67
+ MULTI_SELECT_FORBIDDEN_IN_VALUE = ","
68
+ """Substring a `multi_select` choice value must not contain.
69
+
70
+ Deliberately stated outright rather than derived from
71
+ `MULTI_SELECT_ANSWER_SEPARATOR`, so the two can evolve independently: a separator
72
+ of `" and "` would, if the forbidden text were derived from it, reject every value
73
+ containing "and".
74
+
75
+ This buys *legibility* of the joined answer, not invertibility. Nothing decodes a
76
+ multi-select answer back into its components, and per
77
+ `format_ask_user_transcript` the transcript is not unambiguously decodable
78
+ anyway. If one is ever written, that is the moment to introduce a structured
79
+ answer type instead of leaning on this ban.
80
+ """
81
+
19
82
 
20
83
  class Choice(TypedDict):
21
- """A single choice option for a multiple choice question."""
84
+ """A single choice option for a multiple choice or multi-select question."""
22
85
 
23
- value: Annotated[str, Field(description="The display label for this choice.")]
86
+ value: Annotated[
87
+ str,
88
+ Field(
89
+ description=(
90
+ "The display label for this choice. Also the text returned as "
91
+ "the answer when this choice is selected."
92
+ )
93
+ ),
94
+ ]
24
95
 
25
96
 
26
97
  class Question(TypedDict):
@@ -29,11 +100,18 @@ class Question(TypedDict):
29
100
  question: Annotated[str, Field(description="The question text to display.")]
30
101
 
31
102
  type: Annotated[
32
- Literal["text", "multiple_choice"],
103
+ QuestionType,
33
104
  Field(
34
105
  description=(
35
106
  "Question type. 'text' for free-form input, 'multiple_choice' for "
36
- "predefined options."
107
+ "picking exactly one predefined option, 'multi_select' for picking "
108
+ "one or more predefined options. Both choice types always append an "
109
+ "'Other' free-form option automatically; multi-select can accept "
110
+ "multiple custom Other values (filling one reveals another). A "
111
+ "'multi_select' answer comes back as the selected values "
112
+ "(including any custom Other text) joined with ', '; if nothing "
113
+ "is selected on an optional question the answer is an empty "
114
+ "string."
37
115
  )
38
116
  ),
39
117
  ]
@@ -43,8 +121,12 @@ class Question(TypedDict):
43
121
  list[Choice],
44
122
  Field(
45
123
  description=(
46
- "Options for multiple_choice questions. An 'Other' free-form "
47
- "option is always appended automatically."
124
+ "Options for 'multiple_choice' and 'multi_select' questions. "
125
+ "Every choice needs a non-empty 'value'. An 'Other' free-form "
126
+ "option is always appended automatically for both types; "
127
+ "multi-select may collect multiple custom Other values. "
128
+ "'multi_select' values (including custom Other text) must not "
129
+ "contain ',' because the answer joins them with ', '."
48
130
  )
49
131
  ),
50
132
  ]
@@ -53,8 +135,18 @@ class Question(TypedDict):
53
135
  required: NotRequired[
54
136
  Annotated[
55
137
  bool,
138
+ # `strict=True` so a stringly-typed `"false"` is rejected at the tool
139
+ # boundary rather than coerced. Without it pydantic accepts the string,
140
+ # the prompt renders, and then `_ask_user_question_count` — which reads
141
+ # the *raw* tool args and requires a real bool — returns `None`, which
142
+ # drops every answer in the call as same-turn authorization with no
143
+ # error. Strict here keeps the two boundaries agreeing, and makes the
144
+ # coercion loud instead of silently expensive.
56
145
  Field(
57
- description="Whether the user must answer. Defaults to true if omitted."
146
+ description=(
147
+ "Whether the user must answer. Defaults to true if omitted."
148
+ ),
149
+ strict=True,
58
150
  ),
59
151
  ]
60
152
  ]
@@ -75,6 +167,11 @@ class AskUserRequest(TypedDict):
75
167
 
76
168
  ASK_USER_AUTHORIZATION_METADATA_KEY = "deepagents_code_ask_user_authorization"
77
169
  MAX_ASK_USER_AUTHORIZATION_ANSWER_CHARS = 4000
170
+ # These limits bound the receipt-anchored question/answer evidence copied into
171
+ # Auto's classifier prompt. Questions are model-generated and otherwise have no
172
+ # schema length constraint, so they must not be able to exhaust that context.
173
+ MAX_ASK_USER_AUTHORIZATION_QUESTION_CHARS = 4000
174
+ MAX_ASK_USER_AUTHORIZATION_QUESTION_TOTAL_CHARS = 8000
78
175
 
79
176
 
80
177
  class AskUserAuthorizationReceipt(TypedDict):
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "fbd5ac3"
3
+ BUILD_COMMIT = "57e15ea"
@@ -10,7 +10,7 @@ editable `direct_url.json` record and skip the check entirely, so end
10
10
  users pay no startup cost here.
11
11
 
12
12
  Interactive launches on a terminal stop on a blocking pre-TUI prompt
13
- (continue / mute / abort); headless launches, subcommands, and interactive
13
+ (refresh / continue / mute / abort); headless launches, subcommands, and interactive
14
14
  launches whose stdin is piped get a single stderr warning per launch instead,
15
15
  since they have no answerable prompt and must never block. A dismissed
16
16
  (muted) mismatch is remembered per checkout as a fingerprint of the offending
@@ -25,7 +25,8 @@ import json
25
25
  import logging
26
26
  import os
27
27
  import shlex
28
- import subprocess # noqa: S404 # only `list2cmdline` string quoting, never executed
28
+ import shutil
29
+ import subprocess # noqa: S404 # fixed-argv environment refresh and Windows quoting
29
30
  import sys
30
31
  import tempfile
31
32
  import threading
@@ -40,6 +41,8 @@ from deepagents_code.config import _is_editable_install
40
41
  if TYPE_CHECKING:
41
42
  from collections.abc import Iterator
42
43
 
44
+ from rich.console import Console
45
+
43
46
  from deepagents_code.main import _TrustPromptOutcome
44
47
 
45
48
  logger = logging.getLogger(__name__)
@@ -259,17 +262,177 @@ def _checkout_root() -> Path:
259
262
  return Path(__file__).resolve().parent.parent
260
263
 
261
264
 
265
+ def _is_editable_dist(dist_name: str, path: Path) -> bool:
266
+ """Check whether an installed distribution is an editable install of `path`.
267
+
268
+ Reads the distribution's own PEP 610 `direct_url.json` rather than the
269
+ directory's existence: most `[tool.uv.sources]` entries back optional
270
+ extras, so a source directory that merely exists in a full monorepo
271
+ checkout must not be reinstalled as an editable over an environment that
272
+ deliberately tracks the released wheel.
273
+
274
+ Args:
275
+ dist_name: Distribution name as passed to `importlib.metadata`.
276
+ path: The source checkout the `[tool.uv.sources]` entry points at.
277
+
278
+ Returns:
279
+ `True` when the distribution is installed editable with a `file://`
280
+ URL resolving to `path`; `False` for wheel installs, missing
281
+ distributions, and unreadable or mismatched metadata.
282
+ """
283
+ try:
284
+ raw = importlib.metadata.distribution(dist_name).read_text("direct_url.json")
285
+ if not raw:
286
+ return False
287
+ data = json.loads(raw)
288
+ except (
289
+ importlib.metadata.PackageNotFoundError,
290
+ json.JSONDecodeError,
291
+ TypeError,
292
+ ):
293
+ return False
294
+ if not isinstance(data, dict):
295
+ return False
296
+ dir_info = data.get("dir_info")
297
+ if not isinstance(dir_info, dict) or dir_info.get("editable") is not True:
298
+ return False
299
+ url = data.get("url", "")
300
+ if not isinstance(url, str) or not url.startswith("file://"):
301
+ return False
302
+ from deepagents_code.extras_info import _file_url_to_path
303
+
304
+ recorded = _file_url_to_path(url)
305
+ # `_file_url_to_path` preserves the `netloc` host, so UNC installs such as
306
+ # `file://server/share/repo` compare equal to the same UNC checkout here;
307
+ # parsing only `urlparse(url).path` would drop the server and omit the
308
+ # editable from the refresh, replacing it with a PyPI wheel.
309
+ return recorded is not None and recorded.resolve() == path
310
+
311
+
312
+ def _workspace_editable_paths() -> list[Path]:
313
+ """List the workspace sources this environment actually installed editable.
314
+
315
+ Reads the checkout's own `[tool.uv.sources]`, then keeps only the entries
316
+ whose distribution is currently installed as an editable pointing at that
317
+ same path. Directory existence alone is not enough: partner packages
318
+ (`langchain-daytona`, `langchain-modal`, ...) are optional extras whose
319
+ checkouts always exist in a full monorepo clone, and re-passing them as
320
+ `-e` would replace their released wheels with editables and pull in their
321
+ transitive dependencies.
322
+
323
+ Returns:
324
+ Absolute paths of `editable = true` path sources whose distribution is
325
+ installed editable from that path, in `pyproject.toml` declaration
326
+ order. Empty when the checkout's `pyproject.toml` cannot be read or no
327
+ source qualifies.
328
+ """
329
+ pyproject = _checkout_root() / "pyproject.toml"
330
+ try:
331
+ data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
332
+ sources = data["tool"]["uv"]["sources"]
333
+ except (OSError, KeyError, TypeError, tomllib.TOMLDecodeError):
334
+ logger.debug(
335
+ "Could not read workspace sources from the source checkout",
336
+ exc_info=True,
337
+ )
338
+ return []
339
+ if not isinstance(sources, dict):
340
+ return []
341
+ checkout = _checkout_root()
342
+ paths: list[Path] = []
343
+ for dist_name, source in sources.items():
344
+ if not isinstance(source, dict):
345
+ continue
346
+ if source.get("editable") is not True or not isinstance(
347
+ source.get("path"), str
348
+ ):
349
+ continue
350
+ path = (checkout / source["path"]).resolve()
351
+ if path.is_dir() and _is_editable_dist(dist_name, path):
352
+ paths.append(path)
353
+ return paths
354
+
355
+
356
+ def _refresh_args(uv_path: str) -> list[str]:
357
+ """Build the fixed argv used to refresh this editable environment.
358
+
359
+ Args:
360
+ uv_path: Absolute path to the resolved `uv` binary. Bare names are
361
+ never used: on Windows `subprocess` searches the current working
362
+ directory before `%PATH%`, so a planted `uv.exe` at the project
363
+ root would execute instead of the legitimate binary.
364
+
365
+ Returns:
366
+ Arguments for the user-approved `uv pip install` process.
367
+ """
368
+ checkout = _checkout_root()
369
+ args = [
370
+ uv_path,
371
+ "pip",
372
+ "install",
373
+ "--python",
374
+ sys.executable,
375
+ "-e",
376
+ str(checkout),
377
+ ]
378
+ for path in _workspace_editable_paths():
379
+ args.extend(["-e", str(path)])
380
+ args.append("--upgrade")
381
+ return args
382
+
383
+
262
384
  def refresh_command() -> str:
263
385
  """Return the shell command that refreshes this editable environment.
264
386
 
265
- Shared by the stderr warning and the interactive prompt so the two
266
- channels cannot drift apart.
387
+ Workspace sibling editables are included explicitly because resolving only
388
+ `libs/code` would let `--upgrade` replace them with PyPI wheels. The
389
+ warning and interactive refresh share this argv so they cannot drift.
267
390
  """
268
- return (
269
- "uv pip install --python "
270
- f"{_quote_arg(sys.executable)} -e {_quote_arg(str(_checkout_root()))} "
271
- "--upgrade"
272
- )
391
+ uv_path = shutil.which("uv")
392
+ if uv_path is None:
393
+ return "uv pip install --python <python> -e <checkout> --upgrade"
394
+ return " ".join(_quote_arg(arg) for arg in _refresh_args(uv_path))
395
+
396
+
397
+ def _refresh_environment(console: Console) -> bool:
398
+ """Refresh the active environment after the user explicitly requests it.
399
+
400
+ Args:
401
+ console: Console used for progress and failure messages.
402
+
403
+ Returns:
404
+ `True` when `uv` exits successfully, otherwise `False`.
405
+ """
406
+ uv_path = shutil.which("uv")
407
+ if uv_path is None:
408
+ console.print(
409
+ "[yellow]Environment refresh failed: `uv` not found on PATH.[/yellow]",
410
+ highlight=False,
411
+ )
412
+ return False
413
+ console.print("[dim]Refreshing environment...[/dim]", highlight=False)
414
+ try:
415
+ result = subprocess.run( # noqa: S603 # fixed uv argv, never a shell command
416
+ _refresh_args(uv_path),
417
+ check=False,
418
+ shell=False,
419
+ )
420
+ except OSError as exc:
421
+ from rich.markup import escape
422
+
423
+ console.print(
424
+ f"[yellow]Environment refresh failed: {escape(str(exc))}[/yellow]",
425
+ highlight=False,
426
+ )
427
+ return False
428
+ if result.returncode != 0:
429
+ console.print(
430
+ "[yellow]Environment refresh failed with exit code "
431
+ f"{result.returncode}; choose another action or try again.[/yellow]",
432
+ highlight=False,
433
+ )
434
+ return False
435
+ return True
273
436
 
274
437
 
275
438
  def _collect_violations() -> list[_FloorViolation]:
@@ -516,7 +679,7 @@ def warn_if_editable_deps_stale() -> None:
516
679
 
517
680
 
518
681
  def prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
519
- """Block on a continue/mute/abort prompt when an interactive launch is stale.
682
+ """Block on a refresh/continue/mute/abort prompt for a stale interactive launch.
520
683
 
521
684
  Prompts only when violations exist and the exact mismatch was not muted
522
685
  for this checkout. The prompt itself is implemented in `main` next to the
@@ -544,6 +707,7 @@ def _prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
544
707
  from rich.console import Console
545
708
 
546
709
  from deepagents_code.main import (
710
+ _restart_current_process,
547
711
  _TrustAction,
548
712
  _TrustPromptOutcome,
549
713
  prompt_for_dep_floor_mismatch,
@@ -552,36 +716,65 @@ def _prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
552
716
  violations = _collect_violations()
553
717
  if not violations:
554
718
  return None
555
- fingerprint = _mismatch_fingerprint(violations)
556
- if is_dep_floor_mismatch_muted(fingerprint):
719
+ if is_dep_floor_mismatch_muted(_mismatch_fingerprint(violations)):
557
720
  return None
558
721
 
559
722
  console = Console(stderr=True)
560
- action = prompt_for_dep_floor_mismatch(console, violations)
561
- if action in {_TrustPromptOutcome.INTERRUPTED, _TrustPromptOutcome.CANCELLED}:
562
- return action
563
- if action is _TrustAction.REMEMBER:
564
- if mute_dep_floor_mismatch(fingerprint):
723
+ while True:
724
+ fingerprint = _mismatch_fingerprint(violations)
725
+ action = prompt_for_dep_floor_mismatch(console, violations)
726
+ if action in {
727
+ _TrustPromptOutcome.INTERRUPTED,
728
+ _TrustPromptOutcome.CANCELLED,
729
+ }:
730
+ return action
731
+ if action is _TrustAction.REFRESH:
732
+ if not _refresh_environment(console):
733
+ continue
734
+ violations = _collect_violations()
735
+ if violations:
736
+ continue
565
737
  console.print(
566
- "[dim]Muted until the dependency mismatch changes.[/dim]",
738
+ "[dim]Environment refreshed; relaunching.[/dim]",
567
739
  highlight=False,
568
740
  )
569
- else:
741
+ # Re-exec rather than continuing in-process: dependencies imported
742
+ # before this prompt (`rich`, `python-dotenv`, ...) keep their
743
+ # stale module objects in memory even after `uv` swaps the dists
744
+ # on disk, so only a fresh interpreter runs the refreshed code.
745
+ # The relaunched process re-runs this check, finds no violations
746
+ # (the precondition for reaching here), and never re-prompts — a
747
+ # refresh that silently no-ops fails the re-check above instead,
748
+ # so this cannot loop. `OSError` from a failed exec propagates to
749
+ # the best-effort boundary in `prompt_if_editable_deps_stale`,
750
+ # which continues this (stale but user-approved) launch.
751
+ _restart_current_process()
752
+ return None # unreachable; exec failure raises, per its contract
753
+ if action is _TrustAction.REMEMBER:
754
+ if mute_dep_floor_mismatch(fingerprint):
755
+ console.print(
756
+ "[dim]Muted until the dependency mismatch changes.[/dim]",
757
+ highlight=False,
758
+ )
759
+ else:
760
+ console.print(
761
+ "[yellow]The dismissal could not be saved; you will be asked "
762
+ "again next launch.[/yellow]",
763
+ highlight=False,
764
+ )
765
+ elif action is _TrustAction.ALLOW_ONCE:
570
766
  console.print(
571
- "[yellow]The dismissal could not be saved; you will be asked "
572
- "again next launch.[/yellow]",
767
+ "[dim]Continuing this session; you will be asked again next "
768
+ "launch.[/dim]",
573
769
  highlight=False,
574
770
  )
575
- elif action is _TrustAction.ALLOW_ONCE:
576
- console.print(
577
- "[dim]Continuing this session; you will be asked again next launch.[/dim]",
578
- highlight=False,
579
- )
580
- else:
581
- # `abort_on_deny` should have collapsed a refusal into `CANCELLED`
582
- # already, so `DENY` (or any future outcome) only lands here if that
583
- # mapping regresses. Refuse rather than continuing: matching "continue"
584
- # by default is what previously turned "Abort launch" into a launch.
585
- logger.debug("Unexpected dependency floor prompt outcome %r; aborting", action)
586
- return _TrustPromptOutcome.CANCELLED
587
- return None
771
+ else:
772
+ # `abort_on_deny` should have collapsed a refusal into `CANCELLED`
773
+ # already, so `DENY` (or any future outcome) only lands here if that
774
+ # mapping regresses. Refuse rather than continuing: matching "continue"
775
+ # by default is what previously turned "Abort launch" into a launch.
776
+ logger.debug(
777
+ "Unexpected dependency floor prompt outcome %r; aborting", action
778
+ )
779
+ return _TrustPromptOutcome.CANCELLED
780
+ return None
@@ -117,6 +117,27 @@ Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` (case-insensitive)
117
117
  as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled.
118
118
  """
119
119
 
120
+ DEBUG_COLD_CACHE = "DEEPAGENTS_CODE_DEBUG_COLD_CACHE"
121
+ """Force the cold prompt-cache warning modal on every interactive send.
122
+
123
+ Set to a truthy value when launching the interactive TUI to make
124
+ `_cold_cache_warning_for` synthesize a warning from the current model and
125
+ context, bypassing the provider-policy, token-floor, cache-window, and
126
+ cost-threshold gates as well as both session and persisted suppression. Lets
127
+ the modal be exercised without waiting out a provider cache window.
128
+
129
+ The flag is re-read on every send and nothing clears it, so the modal fires
130
+ for the life of the process, not just once.
131
+
132
+ When the active model has no documented cache policy, `debug_stand_in_policy`
133
+ supplies an Anthropic-shaped placeholder. On a non-Anthropic model the modal
134
+ will therefore cite Anthropic's retention window, and the dollar figures are
135
+ illustrative rather than real estimates.
136
+
137
+ Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` (case-insensitive)
138
+ as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled.
139
+ """
140
+
120
141
  DEBUG_CONSOLE_CLICK_TO_COPY = "DEEPAGENTS_CODE_DEBUG_CONSOLE_CLICK_TO_COPY"
121
142
  r"""Enable click-to-copy in the `Ctrl+\` Debug Console when enabled.
122
143
 
@@ -284,6 +305,18 @@ The value is comma-separated for forward-compatibility, not because multiple
284
305
  destinations are written today.
285
306
  """
286
307
 
308
+ LAUNCH_TERM_PROGRAM = "DEEPAGENTS_CODE_LAUNCH_TERM_PROGRAM"
309
+ """Internal sentinel recording the `TERM_PROGRAM` present when `dcode` started.
310
+
311
+ Not user-facing. The resume hint echoes `TERM_PROGRAM` only when the launch
312
+ environment supplied it (an inline `TERM_PROGRAM=x dcode`, a terminal's own
313
+ export, or a shell alias), so the value set by a project or global `.env` file
314
+ *after* launch must not leak in. The app itself never sets `TERM_PROGRAM`, so
315
+ `cli_main` snapshotting the variable here at entry means a set sentinel always
316
+ marks an explicit launch value; the update re-exec inherits it unchanged,
317
+ which is correct because the relaunch runs the command the user typed.
318
+ """
319
+
287
320
  LEGACY_ENABLED_PROJECT_MCP_SERVERS = "DEEPAGENTS_CODE_ENABLED_PROJECT_MCP_SERVERS"
288
321
  """Removed project MCP allowlist env var retained for migration detection only.
289
322