deepagents-code 0.1.51__tar.gz → 0.1.52__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 (467) hide show
  1. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/CHANGELOG.md +17 -0
  2. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/COMMANDS.md +1 -1
  3. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/HOOKS.md +19 -2
  4. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/PKG-INFO +2 -2
  5. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/THREAT_MODEL.md +20 -3
  6. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_build_info.py +1 -1
  7. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_cli_context.py +32 -0
  8. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_constants.py +3 -0
  9. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_env_vars.py +68 -6
  10. deepagents_code-0.1.52/deepagents_code/_markdown.py +26 -0
  11. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_server_config.py +14 -0
  12. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_version.py +1 -1
  13. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/agent.py +38 -25
  14. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/app.py +565 -61
  15. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auto_mode.py +474 -56
  16. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/config.py +13 -1
  17. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/server_manager.py +8 -0
  18. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/non_interactive.py +32 -5
  19. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/command_registry.py +12 -3
  20. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/config.py +109 -10
  21. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/config_manifest.py +182 -8
  22. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/configurable_model.py +4 -0
  23. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/cost_tracking.py +211 -3
  24. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/engine.py +6 -0
  25. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/loading.py +191 -33
  26. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/manager.py +38 -12
  27. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/domain.py +0 -2
  28. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/runtime.py +18 -0
  29. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/server_middleware.py +18 -5
  30. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/snapshot.py +27 -9
  31. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/trust.py +83 -27
  32. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/main.py +145 -6
  33. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/offload_middleware.py +175 -1
  34. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/onboarding.py +17 -4
  35. deepagents_code-0.1.52/deepagents_code/plugins/adapters/hooks.py +157 -0
  36. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/manifest.py +44 -3
  37. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/models.py +9 -4
  38. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/server_graph.py +1 -0
  39. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/content.py +10 -9
  40. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/models.py +6 -0
  41. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/state.py +4 -0
  42. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/textual_adapter.py +40 -7
  43. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/approval.py +96 -16
  44. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/auto_mode_notice.py +81 -5
  45. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/cwd_switch.py +81 -0
  46. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/model_selector.py +99 -51
  47. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/startup_tip.py +2 -1
  48. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/status.py +6 -1
  49. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/ui.py +8 -0
  50. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/pyproject.toml +2 -2
  51. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/conftest.py +20 -2
  52. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_configuration.py +15 -0
  53. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_engine.py +3 -3
  54. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_manager.py +2 -9
  55. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_server_lifecycle.py +55 -6
  56. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_trust.py +217 -13
  57. deepagents_code-0.1.52/tests/unit_tests/plugins/test_plugin_hooks.py +150 -0
  58. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_agent.py +135 -6
  59. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_app.py +667 -30
  60. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auto_mode.py +1124 -101
  61. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_compact_tool.py +70 -1
  62. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config.py +92 -0
  63. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config_manifest.py +494 -0
  64. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_configurable_model.py +26 -0
  65. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cost_tracking.py +398 -1
  66. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug_console.py +25 -2
  67. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main.py +92 -0
  68. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main_acp_mode.py +24 -0
  69. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main_args.py +95 -0
  70. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_model_config.py +2 -2
  71. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_non_interactive.py +56 -6
  72. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_onboarding.py +34 -7
  73. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reload.py +68 -0
  74. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_config.py +43 -0
  75. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_graph.py +1 -0
  76. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +1 -1
  77. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/test_textual_adapter.py +156 -10
  78. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_approval.py +259 -15
  79. deepagents_code-0.1.52/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +100 -0
  80. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_model_selector.py +221 -49
  81. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_status.py +36 -8
  82. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/uv.lock +6 -6
  83. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/.gitignore +0 -0
  84. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/AGENTS.md +0 -0
  85. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/ARCHITECTURE.md +0 -0
  86. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/DEVELOPMENT.md +0 -0
  87. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/LICENSE +0 -0
  88. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/Makefile +0 -0
  89. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/README.md +0 -0
  90. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/__init__.py +0 -0
  91. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/__main__.py +0 -0
  92. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_ask_user_types.py +0 -0
  93. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_debug.py +0 -0
  94. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_debug_buffer.py +0 -0
  95. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_fake_models.py +0 -0
  96. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_git.py +0 -0
  97. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_glm_5p2_profile.py +0 -0
  98. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_invocation.py +0 -0
  99. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_paths.py +0 -0
  100. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_repository_bounds.py +0 -0
  101. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_session_stats.py +0 -0
  102. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_startup_error.py +0 -0
  103. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_testing_models.py +0 -0
  104. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_textual_patches.py +0 -0
  105. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_tool_stream.py +0 -0
  106. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/app.tcss +0 -0
  107. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/approval_mode.py +0 -0
  108. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/ask_user.py +0 -0
  109. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auth_display.py +0 -0
  110. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auth_store.py +0 -0
  111. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/__init__.py +0 -0
  112. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
  113. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
  114. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  115. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  116. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  117. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  118. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/__init__.py +0 -0
  119. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/__init__.py +0 -0
  120. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/auth.py +0 -0
  121. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/extras.py +0 -0
  122. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/mcp.py +0 -0
  123. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/tools.py +0 -0
  124. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/__init__.py +0 -0
  125. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/server.py +0 -0
  126. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/remote_client.py +0 -0
  127. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/clipboard.py +0 -0
  128. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/default_agent_prompt.md +0 -0
  129. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/doctor.py +0 -0
  130. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/editor.py +0 -0
  131. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/event_bus.py +0 -0
  132. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/extras_info.py +0 -0
  133. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/file_ops.py +0 -0
  134. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/formatting.py +0 -0
  135. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_rubric.py +0 -0
  136. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_state_notice.py +0 -0
  137. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_tools.py +0 -0
  138. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/__init__.py +0 -0
  139. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/capabilities.py +0 -0
  140. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/client.py +0 -0
  141. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/client_lifecycle.py +0 -0
  142. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/context.py +0 -0
  143. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/env.py +0 -0
  144. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/envelope.py +0 -0
  145. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/interrupt.py +0 -0
  146. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/legacy.py +0 -0
  147. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/migration.py +0 -0
  148. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/__init__.py +0 -0
  149. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/adapters.py +0 -0
  150. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/config.py +0 -0
  151. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/transport.py +0 -0
  152. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/wire.py +0 -0
  153. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/permissions.py +0 -0
  154. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/presenter.py +0 -0
  155. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/projection.py +0 -0
  156. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/reducer.py +0 -0
  157. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/runner.py +0 -0
  158. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/tools.py +0 -0
  159. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/transcript.py +0 -0
  160. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
  161. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/input.py +0 -0
  162. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/__init__.py +0 -0
  163. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/openai_codex.py +0 -0
  164. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_config.py +0 -0
  165. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_factory.py +0 -0
  166. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_provider.py +0 -0
  167. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_registry.py +0 -0
  168. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/iterm_cursor_guide.py +0 -0
  169. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/json_types.py +0 -0
  170. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/local_context.py +0 -0
  171. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/managed_tools.py +0 -0
  172. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_auth.py +0 -0
  173. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_config.py +0 -0
  174. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_disabled.py +0 -0
  175. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_login_service.py +0 -0
  176. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_oauth_ui.py +0 -0
  177. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/__init__.py +0 -0
  178. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/_registry.py +0 -0
  179. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/base.py +0 -0
  180. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/github.py +0 -0
  181. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/slack.py +0 -0
  182. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_tools.py +0 -0
  183. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/media_utils.py +0 -0
  184. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/memory_guard.py +0 -0
  185. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/model_config.py +0 -0
  186. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/notifications.py +0 -0
  187. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/offload.py +0 -0
  188. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/output.py +0 -0
  189. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/paste_collapse.py +0 -0
  190. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/__init__.py +0 -0
  191. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/_json.py +0 -0
  192. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/__init__.py +0 -0
  193. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/mcp.py +0 -0
  194. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/skills.py +0 -0
  195. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
  196. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/commands_cli.py +0 -0
  197. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/discovery.py +0 -0
  198. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/marketplace.py +0 -0
  199. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/store.py +0 -0
  200. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/substitution.py +0 -0
  201. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/project_utils.py +0 -0
  202. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/py.typed +0 -0
  203. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/reasoning_effort.py +0 -0
  204. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/reliable_rubric.py +0 -0
  205. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/resume_state.py +0 -0
  206. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/sessions.py +0 -0
  207. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/__init__.py +0 -0
  208. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/commands.py +0 -0
  209. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/invocation.py +0 -0
  210. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/load.py +0 -0
  211. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/merge.py +0 -0
  212. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/trust.py +0 -0
  213. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/state_migration.py +0 -0
  214. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/subagents.py +0 -0
  215. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/system_prompt.md +0 -0
  216. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/terminal_capabilities.py +0 -0
  217. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/terminal_escape.py +0 -0
  218. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/theme.py +0 -0
  219. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tool_catalog.py +0 -0
  220. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tool_display.py +0 -0
  221. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tools.py +0 -0
  222. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/__init__.py +0 -0
  223. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/__init__.py +0 -0
  224. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/__init__.py +0 -0
  225. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +0 -0
  226. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
  227. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/screens/__init__.py +0 -0
  228. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/__init__.py +0 -0
  229. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
  230. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
  231. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
  232. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_links.py +0 -0
  233. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_paste_textarea.py +0 -0
  234. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/agent_selector.py +0 -0
  235. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/ask_user.py +0 -0
  236. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/auth.py +0 -0
  237. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/autocomplete.py +0 -0
  238. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/chat_input.py +0 -0
  239. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/codex_auth.py +0 -0
  240. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/debug_console.py +0 -0
  241. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/diff.py +0 -0
  242. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/effort_selector.py +0 -0
  243. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/goal_review.py +0 -0
  244. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/goal_status.py +0 -0
  245. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/history.py +0 -0
  246. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/install_confirm.py +0 -0
  247. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/launch_init.py +0 -0
  248. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/loading.py +0 -0
  249. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_login.py +0 -0
  250. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
  251. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_viewer.py +0 -0
  252. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/message_store.py +0 -0
  253. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/messages.py +0 -0
  254. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_center.py +0 -0
  255. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_detail.py +0 -0
  256. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_settings.py +0 -0
  257. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/plugin_reload.py +0 -0
  258. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
  259. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/skill_trust.py +0 -0
  260. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/subagent_panel.py +0 -0
  261. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/theme_selector.py +0 -0
  262. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
  263. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/thread_selector.py +0 -0
  264. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
  265. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
  266. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_available.py +0 -0
  267. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_confirm.py +0 -0
  268. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_progress.py +0 -0
  269. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/welcome.py +0 -0
  270. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
  271. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/unicode_security.py +0 -0
  272. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/update_check.py +0 -0
  273. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/arxiv-search/SKILL.md +0 -0
  274. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  275. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/langgraph-docs/SKILL.md +0 -0
  276. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/SKILL.md +0 -0
  277. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  278. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  279. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/web-research/SKILL.md +0 -0
  280. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/hatch_build.py +0 -0
  281. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/images/tui.png +0 -0
  282. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/check_imports.py +0 -0
  283. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/debug_server.sh +0 -0
  284. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/generate_commands_catalog.py +0 -0
  285. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/install.sh +0 -0
  286. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/README.md +0 -0
  287. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/__init__.py +0 -0
  288. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/__init__.py +0 -0
  289. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  290. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
  291. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  292. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/conftest.py +0 -0
  293. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_acp_mode.py +0 -0
  294. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_auto_approve_remote.py +0 -0
  295. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_compact_resume.py +0 -0
  296. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
  297. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_offload_server_side.py +0 -0
  298. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_sandbox_factory.py +0 -0
  299. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_sandbox_operations.py +0 -0
  300. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/__init__.py +0 -0
  301. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/__init__.py +0 -0
  302. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/__init__.py +0 -0
  303. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_auth.py +0 -0
  304. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_extras.py +0 -0
  305. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_mcp.py +0 -0
  306. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_tools.py +0 -0
  307. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
  308. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/__init__.py +0 -0
  309. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/models/__init__.py +0 -0
  310. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/models/test_models.py +0 -0
  311. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
  312. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_execution.py +0 -0
  313. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_presenter.py +0 -0
  314. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_transcript.py +0 -0
  315. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/__init__.py +0 -0
  316. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_marketplace.py +0 -0
  317. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_plugins_p0.py +0 -0
  318. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_store.py +0 -0
  319. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/__init__.py +0 -0
  320. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_commands.py +0 -0
  321. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_load.py +0 -0
  322. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_merge.py +0 -0
  323. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_skill_trust.py +0 -0
  324. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_skills_json.py +0 -0
  325. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
  326. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/__init__.py +0 -0
  327. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/conftest.py +0 -0
  328. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +0 -0
  329. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
  330. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test__tool_stream.py +0 -0
  331. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_agent_friendly.py +0 -0
  332. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_approval_mode.py +0 -0
  333. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_args.py +0 -0
  334. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  335. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ask_user_types.py +0 -0
  336. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_display.py +0 -0
  337. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_store.py +0 -0
  338. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
  339. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_charset.py +0 -0
  340. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_clipboard.py +0 -0
  341. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
  342. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_command_registry.py +0 -0
  343. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config_recursion_limit.py +0 -0
  344. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cursor_blink.py +0 -0
  345. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cursor_style.py +0 -0
  346. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug.py +0 -0
  347. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug_buffer.py +0 -0
  348. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_doctor.py +0 -0
  349. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_editor.py +0 -0
  350. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_end_to_end.py +0 -0
  351. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_env_vars.py +0 -0
  352. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_event_bus.py +0 -0
  353. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_exception_handling.py +0 -0
  354. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_extras_info.py +0 -0
  355. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_file_ops.py +0 -0
  356. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_formatting.py +0 -0
  357. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_git.py +0 -0
  358. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
  359. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_criteria_client.py +0 -0
  360. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_rubric.py +0 -0
  361. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_state_notice.py +0 -0
  362. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_state_persistence.py +0 -0
  363. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_tools.py +0 -0
  364. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_hatch_build.py +0 -0
  365. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_hooks.py +0 -0
  366. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_imports.py +0 -0
  367. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_input_parsing.py +0 -0
  368. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_install_command.py +0 -0
  369. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_install_script.py +0 -0
  370. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_invocation.py +0 -0
  371. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  372. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_json_types.py +0 -0
  373. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_local_context.py +0 -0
  374. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_managed_tools.py +0 -0
  375. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_auth.py +0 -0
  376. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_config.py +0 -0
  377. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_disabled.py +0 -0
  378. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_login_service.py +0 -0
  379. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  380. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_tools.py +0 -0
  381. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_media_utils.py +0 -0
  382. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_memory_guard.py +0 -0
  383. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_model_switch.py +0 -0
  384. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_notifications.py +0 -0
  385. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_offload.py +0 -0
  386. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  387. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_output.py +0 -0
  388. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_paths.py +0 -0
  389. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reasoning_effort.py +0 -0
  390. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reliable_rubric.py +0 -0
  391. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_remote_client.py +0 -0
  392. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_repository_bounds.py +0 -0
  393. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_resume_state.py +0 -0
  394. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_rubric_cli.py +0 -0
  395. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_config.py +0 -0
  396. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_factory.py +0 -0
  397. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_provider.py +0 -0
  398. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_registry.py +0 -0
  399. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server.py +0 -0
  400. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_helpers.py +0 -0
  401. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_manager.py +0 -0
  402. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_session_stats.py +0 -0
  403. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sessions.py +0 -0
  404. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_shell_allow_list.py +0 -0
  405. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_skill_invocation.py +0 -0
  406. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_startup_blocking.py +0 -0
  407. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  408. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_state_migration.py +0 -0
  409. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_subagents.py +0 -0
  410. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  411. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_escape.py +0 -0
  412. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  413. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_textual_patches.py +0 -0
  414. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_theme.py +0 -0
  415. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_threads_resume.py +0 -0
  416. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tool_catalog.py +0 -0
  417. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tool_display.py +0 -0
  418. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tracing_replicas.py +0 -0
  419. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_transcript_virtualization.py +0 -0
  420. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ui.py +0 -0
  421. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_unicode_security.py +0 -0
  422. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_update_check.py +0 -0
  423. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_version.py +0 -0
  424. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/__init__.py +0 -0
  425. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_current_thread.py +0 -0
  426. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  427. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
  428. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/__init__.py +0 -0
  429. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/__init__.py +0 -0
  430. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
  431. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
  432. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/__init__.py +0 -0
  433. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_agent_selector.py +0 -0
  434. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_ask_user.py +0 -0
  435. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_auth_widgets.py +0 -0
  436. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
  437. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_chat_input.py +0 -0
  438. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
  439. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
  440. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
  441. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
  442. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_history.py +0 -0
  443. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_inline_prompt.py +0 -0
  444. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
  445. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
  446. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_links.py +0 -0
  447. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
  448. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
  449. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
  450. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +0 -0
  451. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_message_store.py +0 -0
  452. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_messages.py +0 -0
  453. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_center.py +0 -0
  454. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
  455. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_settings.py +0 -0
  456. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_plugin_reload.py +0 -0
  457. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
  458. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
  459. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_startup_tip.py +0 -0
  460. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_subagent_panel.py +0 -0
  461. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
  462. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_thread_selector.py +0 -0
  463. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
  464. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
  465. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
  466. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
  467. {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_welcome.py +0 -0
@@ -2,6 +2,23 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.52](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.51...deepagents-code==0.1.52) (2026-08-04)
6
+
7
+ ### Features
8
+
9
+ - Hooks v2 is now generally available, with support for loading hooks from installed plugins. ([#5307](https://github.com/langchain-ai/deepagents/issues/5307), [#5198](https://github.com/langchain-ai/deepagents/issues/5198))
10
+ - Auto approval classifier configuration now supports selecting the classifier model and setting a review timeout. ([#5205](https://github.com/langchain-ai/deepagents/issues/5205), [#5302](https://github.com/langchain-ai/deepagents/issues/5302))
11
+ - HITL rejection reasons are now framed for the model, and the approval menu makes reject-with-feedback easier to discover. ([#5259](https://github.com/langchain-ai/deepagents/issues/5259), [#5260](https://github.com/langchain-ai/deepagents/issues/5260))
12
+ - Added a tri-state `DEEPAGENTS_CODE_ONBOARDING` environment variable. ([#5301](https://github.com/langchain-ai/deepagents/issues/5301))
13
+ - The `/model` footer Ctrl+N hint now follows the current display mode. ([#5247](https://github.com/langchain-ai/deepagents/issues/5247))
14
+ - The price catalog now refreshes hourly in the background. ([#5264](https://github.com/langchain-ai/deepagents/issues/5264))
15
+ - Updated recommendations to include DeepSeek V4 Flash 0731. ([#5244](https://github.com/langchain-ai/deepagents/issues/5244))
16
+
17
+ ### Bug Fixes
18
+
19
+ - Fixed several Hooks v2 lifecycle issues: session-end teardown is now bounded, hooks refresh after cwd switches, malformed hook resumes are handled, hook stops surface without agent errors, and unused `SessionEndCause` members were removed. ([#5248](https://github.com/langchain-ai/deepagents/issues/5248), [#5249](https://github.com/langchain-ai/deepagents/issues/5249), [#5233](https://github.com/langchain-ai/deepagents/issues/5233), [#5276](https://github.com/langchain-ai/deepagents/issues/5276), [#5240](https://github.com/langchain-ai/deepagents/issues/5240))
20
+ - `PreCompact` now fires before auto-compaction. ([#5277](https://github.com/langchain-ai/deepagents/issues/5277))
21
+
5
22
  ## [0.1.51](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.50...deepagents-code==0.1.51) (2026-07-31)
6
23
 
7
24
  ### Features
@@ -14,7 +14,7 @@ aliases, descriptions, visibility, or hidden-command metadata.
14
14
  | --- | --- | --- |
15
15
  | `/agents` | | Browse and switch between available agents |
16
16
  | `/auth` | `/connect` | Connect and manage provider and service credentials |
17
- | `/auto` | | Switch to Auto approval mode |
17
+ | `/auto` | | Switch to Auto approval mode, or pick its classifier model for this session |
18
18
  | `/auto-update` | | Turn automatic updates on or off |
19
19
  | `/changelog` | | Open the changelog in a browser |
20
20
  | `/clear` | | Clear the chat and start a new thread |
@@ -10,8 +10,9 @@ Hooks are user-configured shell commands that run at agent lifecycle events. Eac
10
10
  | --- | --- | --- |
11
11
  | User | `~/.deepagents/hooks.json` | Always (when the file exists) |
12
12
  | Project | `{project_root}/.deepagents/hooks.json` | Only after workspace trust |
13
+ | Plugin | `hooks/hooks.json` inside an installed plugin | Whenever the plugin is enabled |
13
14
 
14
- When both scopes load, project matcher groups are applied first, then user groups. A project handler that stops further processing therefore wins over lower-precedence user handlers for the same event.
15
+ Matcher groups are applied project first, then user, then plugin. Precedence decides whose answer wins, not who runs: every matching handler for an event runs concurrently, and their results are then reduced in that order, so the first handler that stops processing decides the event. A plugin handler still executes even when a project or user handler stops the event, so treat a plugin's side effects as unconditional.
15
16
 
16
17
  ### Project workspace trust
17
18
 
@@ -23,6 +24,22 @@ Project-scoped hooks can execute arbitrary commands from the repository. Before
23
24
  - Denying skips project hooks for the session and continues with user hooks only.
24
25
  - Headless / CI runs do not prompt; pass `--trust-project-hooks` to opt in for that run.
25
26
 
27
+ ### Plugin hooks
28
+
29
+ A plugin contributes hooks from `hooks/hooks.json` in its root, from a `hooks` path in its `plugin.json` manifest, or from an inline manifest `hooks` object. The document uses exactly the same shape as a user or project `hooks.json`.
30
+
31
+ Installing and enabling the plugin is the consent gate — workspace trust governs project hooks only, so it neither grants nor withholds a plugin's hooks. Review a plugin before enabling it; the plugin manager lists the events each one hooks. Because the set of server-owned events is fixed when a session starts, newly enabled plugin hooks take effect after `/reload`.
32
+
33
+ Plugin handlers receive their plugin's path variables in the environment. Shell-form `command` handlers expand those variables normally; direct-exec `argv` handlers resolve them before launch. Quote variables in shell commands because installation paths may contain spaces:
34
+
35
+ | Variable | Value |
36
+ | --- | --- |
37
+ | `CLAUDE_PLUGIN_ROOT`, `PLUGIN_ROOT` | The plugin's root directory |
38
+ | `CLAUDE_PLUGIN_DATA`, `PLUGIN_DATA` | The plugin's writable data directory |
39
+ | `CLAUDE_PROJECT_DIR` | The project root |
40
+
41
+ For example, use `"command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""`. Setting `argv` instead avoids shell quoting entirely because those handlers execute directly.
42
+
26
43
  ## Events and matchers
27
44
 
28
45
  Each top-level key under `"hooks"` is an event name. Values are lists of matcher groups. A group may omit `matcher` (or use `"*"`) to match all values for that event's matcher field. Events with no matcher field reject non-wildcard matchers at load time.
@@ -33,7 +50,7 @@ Native tools are matched by their wire names (for example `execute` → `Bash`,
33
50
  | --- | --- | --- | --- |
34
51
  | `SessionStart` | client | `cause` | A session starts (`startup`, `resume`, `clear`, `compact`) |
35
52
  | `UserPromptSubmit` | client | _(none)_ | The user submits a prompt |
36
- | `SessionEnd` | client | `cause` | A session ends |
53
+ | `SessionEnd` | client | `cause` | A session ends (`clear`, `resume`, `prompt_input_exit`, `other`) |
37
54
  | `PermissionRequest` | client | `tool_name` | The client is about to ask for tool permission |
38
55
  | `Notification` | client | `notification_type` | A client lifecycle notification is emitted |
39
56
  | `PreToolUse` | server | `tool_name` | Before a tool call runs |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-code
3
- Version: 0.1.51
3
+ Version: 0.1.52
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.9
32
32
  Requires-Dist: deepagents==0.7.1
33
33
  Requires-Dist: filelock<3.30,>=3.29.7
34
- Requires-Dist: genai-prices<0.2.0,>=0.1.0
34
+ Requires-Dist: genai-prices<0.2.0,>=0.1.1
35
35
  Requires-Dist: httpx<1.0.0,>=0.28.1
36
36
  Requires-Dist: langchain-anthropic<2.0.0,>=1.5.3
37
37
  Requires-Dist: langchain-google-genai<5.0.0,>=4.3.2
@@ -349,6 +349,7 @@
349
349
  | T10 | DF24 | DC1 | MCP stdio subprocess env dict accepts arbitrary keys including `PATH`, `LD_PRELOAD`, `PYTHONPATH` without filtering | TB4 | Low | Verified | `mcp_tools._validate_server_config`, `mcp_tools._load_tools_from_config` |
350
350
  | T12 | DF10 | — | Project `.env` sets shell startup-hook variables (`BASH_ENV`, `ENV`) that run attacker-controlled scripts when `dcode` spawns Bash, before any HITL approval | TB11 | High | Verified | `config._load_dotenv`, `local_context.build_detect_script` |
351
351
  | T13 | DF7 | — | Configured shell allow-list checks only the first token, so an allow-listed interpreter/wrapper (`python3`, `bash`, `env`, `xargs`, …) runs arbitrary code via its arguments without approval in non-interactive mode | TB2 | Medium | Verified | `config.is_shell_command_allowed`, `config.contains_dangerous_patterns` |
352
+ | T14 | DF7, DF9 | — | A weaker model configured for the Auto approval classifier reviews gated actions less reliably, including untrusted text carried in tool arguments and file content | TB2 | Low | Verified | `auto_mode.AutoModeHITLMiddleware._classifier_model`, `config.resolve_auto_classifier_model`, `config_manifest.resolve_auto_classifier_timeout` |
352
353
 
353
354
  ### Threat Details
354
355
 
@@ -419,6 +420,13 @@
419
420
  - **Mitigations**: (1) SHA-256 verified against the pinned hash table before move — a mismatch aborts the install and leaves `BIN_DIR` clean. (2) Network egress is limited to `github.com`. (3) Opt-out via `DEEPAGENTS_CODE_OFFLINE` for air-gapped environments, or `DEEPAGENTS_CODE_RIPGREP_INSTALLER=system` to defer to the OS package manager instead of the managed binary. (4) Pinned version + checksums are bumped in-tree, so a compromised upstream release is detected on the next Deep Agents Code release rather than silently propagating. (5) Atomic move-into-place avoids partial installs when concurrent CLI invocations race. (6) The eager install-script path is non-`sudo` (no system package manager is invoked in the default `managed` mode).
420
421
  - **Preconditions**: User has not installed `rg` via their package manager, `DEEPAGENTS_CODE_OFFLINE` is unset, `DEEPAGENTS_CODE_RIPGREP_INSTALLER` is not `system`, and the host can reach `github.com`. The pinned SHA-256 in `RIPGREP_ASSETS` would need to be incorrect (a supply-chain compromise of the deepagents-code release) for a tampered binary to be installed.
421
422
 
423
+ #### T11b: Unpinned Pricing Catalog Fetched Hourly from a Mutable Upstream Ref
424
+
425
+ - **Flow**: Background daemon thread started by `cost_tracking._start_price_updater` on the first priced model request.
426
+ - **Description**: Unless opted out, Deep Agents Code starts `genai_prices.UpdatePrices`, which fetches `raw.githubusercontent.com/pydantic/genai-prices/refs/heads/main/prices/new_data/v2/data.json` every hour and installs it via `set_custom_snapshot`. The fetched catalog wholesale-replaces the pricing data bundled with the installed package for the life of the process. Unlike the ripgrep download (T11), the payload is **not** checksummed and the URL names a mutable branch ref rather than a pinned release, so the content can change between any two fetches. The blast radius is confined to displayed cost estimates — the catalog is parsed as data by `genai-prices`, never executed — but corrupt, regressed, or hostile upstream data silently changes every cost figure the user sees, and a catalog that omits providers makes lookups fail in a way that reads as "this model has no published rates."
427
+ - **Mitigations**: (1) Opt-out via `DEEPAGENTS_CODE_PRICES_AUTO_UPDATE=0` or `[update].prices_auto_update = false` in `config.toml`, or `DEEPAGENTS_CODE_OFFLINE` for air-gapped environments, all checked before the thread starts. (2) `cost_tracking._build_price_updater` refuses a fetched catalog listing fewer providers than the bundled one, so a truncated or mid-publish `data.json` cannot take effect. (3) A refused or failed fetch leaves the previously installed catalog in place rather than clearing it. (4) `genai-prices` rejects any payload that is not a JSON array of schema-valid providers. (5) Network egress is limited to `raw.githubusercontent.com`. (6) The updater is started lazily on first pricing, never at CLI startup, so a session that prices nothing makes no request.
428
+ - **Preconditions**: `DEEPAGENTS_CODE_PRICES_AUTO_UPDATE` is not falsy, `DEEPAGENTS_CODE_OFFLINE` is unset, the host can reach `raw.githubusercontent.com`, and at least one model request is priced. For tampered data to be installed, the upstream repository or the CDN path would need to be compromised **and** the substituted catalog would need to list at least as many providers as the bundled data.
429
+
422
430
  #### T12: Project `.env` Injects Shell Interpreter Startup Hooks
423
431
 
424
432
  - **Flow**: DF10 (project `.env` → process environment) → bash subprocess startup (DF19)
@@ -431,6 +439,12 @@
431
439
  - **Description**: `is_shell_command_allowed` splits a command on `|`, `;`, `&&`, and `||`, then validates only the *first token* (`tokens[0]`) of each segment against the configured allow-list, after rejecting a set of dangerous patterns (`contains_dangerous_patterns`: command substitution `$(`/backticks, redirects, `${`, bare `$VAR`, background `&`). Because only the executable name is checked, any allow-listed general-purpose interpreter or command wrapper carries arbitrary behavior in its arguments: `python3 -c '<code>'`, `bash script.sh`, `sh -c '<code>'`, `env <cmd>`, `xargs <cmd>`, `uv run <cmd>`, and similar. A user who allow-lists such a program — reasonably believing they have restricted the agent to a "safe" tool — has effectively allowed unrestricted execution, and in headless `-x`/Auto mode those commands run without an approval prompt. This is the same class of weakness as T2 but applies to *normal, non-`all`* allow-lists. The allow-list is an ergonomic auto-approve heuristic, not a security boundary; textual command classification cannot robustly constrain execution.
432
440
  - **Preconditions**: (1) User configures a shell allow-list (`--shell-allow-list` / `DEEPAGENTS_SHELL_ALLOW_LIST`) that includes an interpreter or wrapper; (2) non-interactive or Auto mode (interactive Manual mode still shows the human the literal command before it runs); (3) for the injected-command variant, successful prompt injection via DF8/DF9. The intended control is HITL approval; OS-native execution sandboxing would be the robust boundary the string allow-list cannot provide.
433
441
 
442
+ #### T14: Weaker Auto Classifier Model Weakens Action Review
443
+
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`).
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
+
434
448
  ---
435
449
 
436
450
  ## Input Source Coverage
@@ -438,10 +452,10 @@
438
452
  | Input Source | Data Flows | Threats | Validation Points | Responsibility | Gaps |
439
453
  |-----------------------|-----------------------|---------------|----------------------------------------------------------------------------|----------------|----------------------------------------------------------------------------------------------|
440
454
  | User direct input | DF1, DF2 | None (TB1) | None — prompts accepted verbatim | User | No content filtering — intentional; HITL gates downstream tool calls |
441
- | LLM output | DF6, DF7 | T1, T2, T3, T4, T13| HITL gate; shell allow-list; Unicode/URL warnings on tool args | 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) |
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) |
442
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 |
443
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 |
444
- | Configuration | DF10, DF12, DF15, DF23| T9, T10, T12 | Dotenv shell-env precedence; TOML schema; MCP schema + allow/deny lists; JSON structure check; `class_path` format check | User | Project `.env` can set shell startup-hook vars; `class_path` executes module code before type check; MCP env dict unfiltered |
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) |
445
459
  | Session restore | DF14 | T5 | OS file permissions; SQLite | Project | Unencrypted at rest |
446
460
  | 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 |
447
461
  | Host environment | DF19, DF20 | T7 | Static script; exit code check; 30s timeout | Shared | Makefile content injected into system prompt without sanitization |
@@ -463,7 +477,7 @@ Threats that appear valid in isolation but fall outside project responsibility b
463
477
  | Malicious MCP server injecting prompt instructions | Users configure MCP servers and explicitly trust project-level configs. Once trusted, MCP tool outputs are data from a system the user controls. | Interactive approval prompt + per-server allow/deny lists for project-level configs (`main._check_mcp_project_trust`, `model_config.load_mcp_server_trust_lists`). |
464
478
  | LLM jailbreak / safety bypass | Model selection and safety configuration are user-controlled. The project routes prompts to the configured LLM but cannot guarantee model behavior. | Correctly routing prompts to the configured LLM; applying the system prompt from `agent.get_system_prompt`. |
465
479
  | Sandbox provider security vulnerabilities | Daytona, LangSmith, Modal, Runloop, and AgentCore are third-party services. Their internal security is not this project's responsibility. | Correctly initializing sandbox sessions via `integrations.sandbox_factory.create_sandbox`. |
466
- | Hook commands doing harmful things | User-scoped hooks (`~/.deepagents/hooks.json`) and project-scoped hooks (`.deepagents/hooks.json`, only after interactive workspace trust or `--trust-project-hooks`) are intentionally configured commands. The payload is data-only (JSON on stdin). | Schema validation (`hooks.loading.load_hooks_config`); workspace trust for project hooks (versioned store under `~/.deepagents/.state/hooks_trust.json`; cancelling the trust prompt aborts startup); bounded execution with per-event default timeouts (600s for most events, 30s for `UserPromptSubmit`); sanitized subprocess environment. |
480
+ | Hook commands doing harmful things | User-scoped hooks (`~/.deepagents/hooks.json`), project-scoped hooks (`.deepagents/hooks.json`, only after interactive workspace trust or `--trust-project-hooks`), and plugin-scoped hooks (`hooks/hooks.json` in a plugin the user installed and enabled) are intentionally configured commands. The payload is data-only (JSON on stdin). | Schema validation (`hooks.loading.load_hooks_config`); workspace trust for project hooks (versioned store under `~/.deepagents/.state/hooks_trust.json`; cancelling the trust prompt aborts startup); install plus enablement for plugin hooks, with declared events listed in the plugin manager; bounded execution with per-event default timeouts (600s for most events, 30s for `UserPromptSubmit`); sanitized subprocess environment with only the plugin's own path variables overlaid. |
467
481
  | Async subagent traffic interception / MitM | Async subagents connect to user-configured LangGraph deployment URLs. The project does not control those endpoints or their TLS certificates. | Accepting URL/headers from user config and passing them to the LangGraph SDK (`agent.load_async_subagents`). |
468
482
  | LangGraph dev server port enumeration / discovery | Discovering the local dev server port requires local access. Port scanning localhost is a general OS security concern, not a framework vulnerability. | Binding to `127.0.0.1` by default (`server._DEFAULT_HOST`); ephemeral server lifetime; OS-assigned ephemeral port (`server._EPHEMERAL_PORT`) is not predictable across runs. |
469
483
  | `.env` file from parent directory changes app/API configuration | `config._find_dotenv_from_start_path` walks up the directory tree to find `.env` files. Discovering ordinary configuration values (API keys, `DEEPAGENTS_CODE_*` settings) this way is standard `python-dotenv` behavior, and the user controls their filesystem. The *code-execution* implication of a project `.env` (shell startup hooks) is tracked in-scope as T12. | Finding `.env` from the project root (`config._find_dotenv_from_start_path`); `override=False` by default (existing env vars preserved); shell startup / environment-hijack keys (`BASH_ENV`, `ENV`) denied during dotenv loading. |
@@ -504,3 +518,6 @@ Threats that appear valid in isolation but fall outside project responsibility b
504
518
  | 2026-07-21 | manual update | Clarified TB4 after process-wide MCP names and scoped remembered approvals changed from replacement semantics to independent grants. An empty process-wide allowlist no longer suppresses remembered approvals; disabled-server precedence is unchanged. |
505
519
  | 2026-07-22 | manual update | Added T13 (first-token shell allow-list bypass via allow-listed interpreters/wrappers) under TB2, distinguishing it from T2's `--shell-allow-list all` sentinel; cross-referenced it from T2 and extended the "LLM output" input-coverage gap to note that allow-list matching only inspects the command's first token |
506
520
  | 2026-07-24 | manual update | Corrected the out-of-scope hooks row: Hooks v2 defaults are 600s (30s for `UserPromptSubmit`), not a global 5-second timeout; loading is `hooks.loading.load_hooks_config`; project hooks require workspace trust or `--trust-project-hooks` |
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
+ | 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
+ | 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 |
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "d2b663f"
3
+ BUILD_COMMIT = "b428644"
@@ -11,6 +11,25 @@ from __future__ import annotations
11
11
  from dataclasses import dataclass, field
12
12
  from typing import Any, TypedDict
13
13
 
14
+ INHERIT_CLASSIFIER_MODEL = "__dcode_inherit_classifier__"
15
+ """Per-run `classifier_model` value meaning "review with the main agent model".
16
+
17
+ An absent (or `None`) `classifier_model` only says the run carries no
18
+ preference, so the classifier keeps whatever the server resolved at startup
19
+ (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`,
20
+ `[models].auto_classifier`). `/auto model clear` needs the stronger statement
21
+ that reviews go back to the main agent model, which this sentinel carries.
22
+
23
+ It cannot collide with a real spec: `create_model` resolves `provider:model`
24
+ (or a bare model name) and has no provider or model named `__dcode_...`. A
25
+ control character such as a leading NUL would also be collision-proof, but this
26
+ value has to survive the trip to a remote deployment intact — the context is
27
+ serialized to JSON and may be persisted, and Postgres `text`/`jsonb` rejects NUL
28
+ outright. A stripped sentinel would silently read as "no preference" and leave a
29
+ startup classifier authorizing actions after the UI reported the clear, so the
30
+ sentinel stays plain ASCII.
31
+ """
32
+
14
33
 
15
34
  @dataclass
16
35
  class CLIContextSchema:
@@ -39,6 +58,8 @@ class CLIContextSchema:
39
58
 
40
59
  model_context_limit: int | None = None
41
60
 
61
+ classifier_model: str | None = None
62
+
42
63
  approval_mode: str = "manual"
43
64
 
44
65
  auto_approve: bool = False
@@ -81,6 +102,17 @@ class CLIContext(TypedDict, total=False):
81
102
  model_context_limit: int | None
82
103
  """Effective context-window limit for profile-aware middleware."""
83
104
 
105
+ classifier_model: str | None
106
+ """Model spec the Auto approval classifier should use for this run.
107
+
108
+ `None` (or absent) expresses no per-run preference, so the classifier keeps
109
+ whatever the graph was built with — normally the main agent model, but a
110
+ separate model when the session was launched with one.
111
+ `INHERIT_CLASSIFIER_MODEL` overrides that startup value back to the main
112
+ agent model. Set by `/auto model` so the switch takes effect without
113
+ restarting the agent server.
114
+ """
115
+
84
116
  approval_mode: str
85
117
  """`manual`, classifier-backed `auto`, or unrestricted `yolo`."""
86
118
 
@@ -27,6 +27,9 @@ drift guards in `test_main_args` and `test_tool_catalog` pin it so a new or
27
27
  renamed SDK filesystem tool fails a test instead of silently diverging.
28
28
  """
29
29
 
30
+ SESSION_END_DRAIN_TIMEOUT_SECONDS: Final[float] = 2.0
31
+ """Maximum time to drain Hooks v2 `SessionEnd` during session teardown."""
32
+
30
33
  SDK_DEFAULT_RUBRIC_MAX_ITERATIONS: Final[int] = 3
31
34
  """Default `RubricMiddleware.max_iterations`, shown without importing the SDK.
32
35
 
@@ -30,6 +30,42 @@ import os
30
30
  # Keep alphabetically sorted by constant name.
31
31
  # ---------------------------------------------------------------------------
32
32
 
33
+ AUTO_CLASSIFIER_MODEL = "DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL"
34
+ """Model spec (`provider:model`) used by the Auto approval-mode classifier.
35
+
36
+ Unset (the default) reuses the main agent model, preserving the historical
37
+ behavior. A `provider:model` value points the authorization classifier at a
38
+ separate — typically faster and cheaper — model without changing the model that
39
+ writes code. The classifier is a security control: a model that cannot be
40
+ resolved (bad spec, missing credentials, uninstalled provider package) never
41
+ falls back to the main model — reviewed actions are denied, and repeated
42
+ failures escalate to your approval. Also settable via `[models].auto_classifier`
43
+ in config.toml and `--auto-classifier-model`.
44
+
45
+ This is user-controlled process env, not a repo file: a committed *project*
46
+ `.env` cannot set it (see `config._PROJECT_DOTENV_DENIED_ENV_KEYS`), so a cloned
47
+ repository cannot point the review that authorizes its own tool calls at a weaker
48
+ model. Only the shell, the launch environment, or the global `~/.deepagents/.env`
49
+ can.
50
+ """
51
+
52
+ AUTO_CLASSIFIER_TIMEOUT = "DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT"
53
+ """Seconds the Auto approval-mode classifier may take to review one batch.
54
+
55
+ Raise this when reviews time out on a slow or heavily loaded classifier model:
56
+ a batch that misses the deadline is denied as `classifier_unavailable`, so the
57
+ tool call does not run and repeated misses escalate to your approval. This
58
+ covers the wait for a verdict only — the separate budget for *building* the
59
+ classifier model (cold provider import, credential bootstrap), which denies with
60
+ "could not be built within 30s", is fixed. Values outside 1-300 seconds are
61
+ ignored in favor of the next config source, so the deadline can never be
62
+ removed. Also settable via `[models].auto_classifier_timeout` in config.toml.
63
+ Resolved once per `dcode` start, so a change takes effect on the next launch.
64
+
65
+ Like `AUTO_CLASSIFIER_MODEL`, a committed *project* `.env` cannot set it (see
66
+ `config._PROJECT_DOTENV_DENIED_ENV_KEYS`).
67
+ """
68
+
33
69
  AUTO_UPDATE = "DEEPAGENTS_CODE_AUTO_UPDATE"
34
70
  """Toggle automatic app updates. Enabled by default; set to a falsy value
35
71
  ('0', 'false', 'no', 'off', or empty) to opt out."""
@@ -124,12 +160,6 @@ Does not auto-open the update modal (use `DEEPAGENTS_CODE_DEBUG_UPDATE` for that
124
160
  Any non-empty value enables the flag (including `"0"` or `"false"`).
125
161
  """
126
162
 
127
- DEBUG_ONBOARDING = "DEEPAGENTS_CODE_DEBUG_ONBOARDING"
128
- """Force the onboarding flow to open on every interactive startup.
129
-
130
- Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` as enabled.
131
- """
132
-
133
163
  DEBUG_UPDATE = "DEEPAGENTS_CODE_DEBUG_UPDATE"
134
164
  """Inject a sample update-available notification and auto-open the update modal
135
165
  at launch so the update-available flow can be exercised without waiting for a
@@ -284,6 +314,22 @@ and `/api/show`. See `_ollama_discovery_enabled` for accepted truthy/falsy
284
314
  values.
285
315
  """
286
316
 
317
+ ONBOARDING = "DEEPAGENTS_CODE_ONBOARDING"
318
+ """Override whether the first-run onboarding flow opens at interactive startup.
319
+
320
+ Three-state, parsed by `classify_env_bool`:
321
+
322
+ - Unset (or an unrecognized token): keep the default first-run behavior, i.e.
323
+ run onboarding until the completion marker exists.
324
+ - Falsy (`0`, `false`, `no`, `off`, or empty): never open onboarding, even on a
325
+ fresh install with no completion marker.
326
+ - Truthy (`1`, `true`, `yes`, `on`): force onboarding to open on every
327
+ interactive startup, ignoring the completion marker.
328
+
329
+ Read by `should_run_onboarding`; skipping the flow this way does not write the
330
+ completion marker, so unsetting the variable restores first-run behavior.
331
+ """
332
+
287
333
  ONBOARDING_INTEGRATIONS_SCREEN = "DEEPAGENTS_CODE_ONBOARDING_INTEGRATIONS_SCREEN"
288
334
  """Show the "Installed Integrations" summary screen during first-run onboarding.
289
335
 
@@ -315,6 +361,22 @@ PLUGIN_CACHE_DIR = "DEEPAGENTS_CODE_PLUGIN_CACHE_DIR"
315
361
  When unset, plugins are stored under `DEFAULT_CONFIG_DIR / "plugins"`.
316
362
  """
317
363
 
364
+ PRICES_AUTO_UPDATE = "DEEPAGENTS_CODE_PRICES_AUTO_UPDATE"
365
+ """Toggle hourly background refresh of the `genai-prices` pricing catalog.
366
+
367
+ Enabled by default; set to a falsy value (`0`, `false`, `no`, `off`, or empty)
368
+ to keep using only the pricing data bundled with the installed `genai-prices`
369
+ package. `DEEPAGENTS_CODE_OFFLINE` suppresses the refresh too, along with
370
+ every other network fetch.
371
+
372
+ Parsed by `is_env_truthy` on each pricing call until the updater starts, and
373
+ never read again after that -- so disabling it mid-process has no effect on a
374
+ running updater, while enabling it mid-process starts one on the next priced
375
+ request. Also the escape hatch for hosts embedding this package that manage
376
+ `genai_prices.UpdatePrices` themselves: genai-prices permits one updater per
377
+ process, so an embedder that starts its own would otherwise race this one.
378
+ """
379
+
318
380
  RECURSION_LIMIT = "DEEPAGENTS_CODE_RECURSION_LIMIT"
319
381
  """Override the main agent's LangGraph `recursion_limit` (graph step budget).
320
382
 
@@ -0,0 +1,26 @@
1
+ """Escaping for external text that reaches Rich/Textual markdown source."""
2
+
3
+ from __future__ import annotations
4
+
5
+ MARKDOWN_ESCAPES = str.maketrans({char: f"\\{char}" for char in "\\&`*_[]<>|~"})
6
+ """Translation table backing `escape_markdown`.
7
+
8
+ Covers the inline constructs Rich's markdown parser acts on (emphasis, code
9
+ spans, links, autolinks/HTML, HTML entities, strikethrough) plus the `|`
10
+ table-cell separator. Block-level punctuation (`#`, `-`, `>`) only has meaning
11
+ at the start of a line; line breaks are normalized before translation, and `>`
12
+ is escaped anyway because it is cheap.
13
+ """
14
+
15
+
16
+ def escape_markdown(text: str) -> str:
17
+ """Normalize line breaks and escape markdown syntax in external text.
18
+
19
+ Args:
20
+ text: Display string that may contain markdown punctuation.
21
+
22
+ Returns:
23
+ `text` on one line with markdown-significant characters escaped.
24
+ """
25
+ normalized = text.replace("\r\n", " ").replace("\r", " ").replace("\n", " ")
26
+ return normalized.translate(MARKDOWN_ESCAPES)
@@ -340,6 +340,14 @@ class ServerConfig:
340
340
  rubric_max_iterations: int | None = None
341
341
  """Explicit grader iterations per rubric attempt; `None` uses the SDK default."""
342
342
 
343
+ auto_classifier_model: str | None = None
344
+ """Classifier model spec for Auto mode (e.g. `'anthropic:claude-haiku-4-5'`).
345
+
346
+ `None` falls through to `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, then
347
+ `[models].auto_classifier`, and then to the main agent model. An empty value
348
+ round-trips to `None`, so it means "inherit", never "empty spec".
349
+ """
350
+
343
351
  recursion_limit: int | None = None
344
352
  """Explicit main-agent LangGraph `recursion_limit` (graph step budget).
345
353
 
@@ -477,6 +485,7 @@ class ServerConfig:
477
485
  else None
478
486
  ),
479
487
  "RUBRIC_MODEL": self.rubric_model,
488
+ "AUTO_CLASSIFIER_MODEL": self.auto_classifier_model,
480
489
  "RUBRIC_MAX_ITERATIONS": (
481
490
  str(self.rubric_max_iterations)
482
491
  if self.rubric_max_iterations is not None
@@ -536,6 +545,7 @@ class ServerConfig:
536
545
  ),
537
546
  allow_fs_tools=_read_env_allow_fs_tools(),
538
547
  rubric_model=_read_env_str("RUBRIC_MODEL") or None,
548
+ auto_classifier_model=_read_env_str("AUTO_CLASSIFIER_MODEL") or None,
539
549
  rubric_max_iterations=_read_env_int("RUBRIC_MAX_ITERATIONS", default=None),
540
550
  recursion_limit=_read_env_int("RECURSION_LIMIT", default=None),
541
551
  sandbox_type=_read_env_str("SANDBOX_TYPE"),
@@ -577,6 +587,7 @@ class ServerConfig:
577
587
  allow_fs_tools: list[FsToolName] | None = None,
578
588
  rubric_model: str | None = None,
579
589
  rubric_max_iterations: int | None = None,
590
+ auto_classifier_model: str | None = None,
580
591
  recursion_limit: int | None = None,
581
592
  mcp_config_path: str | None,
582
593
  no_mcp: bool,
@@ -618,6 +629,8 @@ class ServerConfig:
618
629
  rubric_model: Grader model spec; `None` reuses the main model.
619
630
  rubric_max_iterations: Explicit grader iterations per rubric attempt;
620
631
  `None` uses the SDK default.
632
+ auto_classifier_model: Auto classifier model spec; `None` resolves from
633
+ env / `config.toml` and then reuses the main model.
621
634
  recursion_limit: Explicit main-agent `recursion_limit`; `None` resolves
622
635
  from env / `config.toml` / default at agent-build time.
623
636
  mcp_config_path: Path to MCP config.
@@ -651,6 +664,7 @@ class ServerConfig:
651
664
  allow_fs_tools=allow_fs_tools,
652
665
  rubric_model=rubric_model,
653
666
  rubric_max_iterations=rubric_max_iterations,
667
+ auto_classifier_model=auto_classifier_model,
654
668
  recursion_limit=recursion_limit,
655
669
  sandbox_type=sandbox_type,
656
670
  sandbox_id=sandbox_id,
@@ -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.51" # x-release-please-version
5
+ __version__ = "0.1.52" # 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."""
@@ -2200,6 +2200,7 @@ def create_cli_agent(
2200
2200
  enable_interpreter: bool = False,
2201
2201
  rubric_model: str | BaseChatModel | None = None,
2202
2202
  rubric_max_iterations: int | None = None,
2203
+ auto_classifier_model: str | BaseChatModel | None = None,
2203
2204
  recursion_limit: int | None = None,
2204
2205
  checkpointer: BaseCheckpointSaver | None = None,
2205
2206
  mcp_server_info: list[MCPServerInfo] | None = None,
@@ -2325,6 +2326,16 @@ def create_cli_agent(
2325
2326
  rubric_max_iterations: Explicit grader iterations per rubric attempt
2326
2327
  before the agent terminates with `'max_iterations_reached'`; `None`
2327
2328
  uses the SDK default.
2329
+ auto_classifier_model: Model the Auto approval classifier reviews with.
2330
+
2331
+ A `'provider:model'` string or `BaseChatModel`.
2332
+
2333
+ When `None`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is consulted,
2334
+ then `[models].auto_classifier`, and the main `model` is reused when
2335
+ both are unset. A blank string is *not* the same as `None`: it means
2336
+ "inherit the main model" directly and, unlike `None`, does not
2337
+ consult the env var or `config.toml`. Only meaningful when
2338
+ `auto_mode_enabled` is `True`.
2328
2339
  recursion_limit: Explicit LangGraph `recursion_limit` (graph step budget)
2329
2340
  for the main agent. When `None`, it is resolved from the
2330
2341
  `DEEPAGENTS_CODE_RECURSION_LIMIT` env var, `[runtime].recursion_limit`
@@ -2463,21 +2474,17 @@ def create_cli_agent(
2463
2474
  # Server-owned hooks must wrap subagent tools too; otherwise Pre/Post
2464
2475
  # ToolUse only fire on the parent graph. Disable Stop so finishing a
2465
2476
  # subagent does not emit the main-agent Stop event (SubagentStop still
2466
- # fires from the parent wrap around `task`). Hooks v2 stays off unless
2467
- # experimental mode is on.
2468
- from deepagents_code._env_vars import EXPERIMENTAL, is_env_truthy
2469
-
2470
- if is_env_truthy(EXPERIMENTAL):
2471
- from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
2477
+ # fires from the parent wrap around `task`).
2478
+ from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
2472
2479
 
2473
- hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
2474
- middleware.append(
2475
- ServerHooksMiddleware(
2476
- cwd=hooks_cwd,
2477
- emit_stop=False,
2478
- mcp_tools=mcp_tools,
2479
- )
2480
+ hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
2481
+ middleware.append(
2482
+ ServerHooksMiddleware(
2483
+ cwd=hooks_cwd,
2484
+ emit_stop=False,
2485
+ mcp_tools=mcp_tools,
2480
2486
  )
2487
+ )
2481
2488
  # Subagents share the on-disk filesystem backend and can edit the user
2482
2489
  # AGENTS.md, so they get the same managed onboarding-name block guard as
2483
2490
  # the main agent. Gated on memory because the block only exists when
@@ -2844,13 +2851,25 @@ def create_cli_agent(
2844
2851
  compaction_middleware = _create_cli_compaction_middleware(model, composite_backend)
2845
2852
  if auto_mode_config is not None and resolved_interrupt_on is not None:
2846
2853
  from deepagents_code.auto_mode import AutoModeHITLMiddleware
2854
+ from deepagents_code.config import resolve_auto_classifier_model
2855
+ from deepagents_code.config_manifest import resolve_auto_classifier_timeout
2847
2856
 
2848
2857
  trusted_root, narrow_allow_list = auto_mode_config
2858
+ # An explicit argument wins; otherwise the env var / `config.toml`
2859
+ # preference is read here, where agent construction already runs off the
2860
+ # blockbuster-guarded server loop (see `server_graph._make_graph`).
2861
+ classifier_model = (
2862
+ auto_classifier_model
2863
+ if auto_classifier_model is not None
2864
+ else resolve_auto_classifier_model()
2865
+ )
2849
2866
  agent_middleware.append(
2850
2867
  AutoModeHITLMiddleware(
2851
2868
  resolved_interrupt_on,
2852
2869
  worktree_root=trusted_root,
2853
2870
  shell_allow_list=narrow_allow_list,
2871
+ classifier_model=classifier_model,
2872
+ classifier_timeout_seconds=resolve_auto_classifier_timeout(),
2854
2873
  trusted_ask_user_tool=trusted_ask_user_tool,
2855
2874
  trusted_compaction_tool=compaction_middleware.tools[0],
2856
2875
  )
@@ -2862,19 +2881,13 @@ def create_cli_agent(
2862
2881
  agent_middleware.append(AsyncApprovalHITLMiddleware(resolved_interrupt_on))
2863
2882
 
2864
2883
  # Server-owned Hooks v2 lifecycle events (Pre/Post tool, Stop, subagent).
2865
- # Mounted only in experimental mode; when mounted, also gated at runtime by
2866
- # `hooks_server_events` on the per-run context so idle sessions without
2867
- # configured handlers pay no interrupt round-trip. Appended after the HITL
2868
- # middleware so `PreToolUse` resolves before approval routing.
2869
- from deepagents_code._env_vars import EXPERIMENTAL, is_env_truthy
2870
-
2871
- if is_env_truthy(EXPERIMENTAL):
2872
- from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
2884
+ # Gated at runtime by `hooks_server_events` on the per-run context so idle
2885
+ # sessions without configured handlers pay no interrupt round-trip. Appended
2886
+ # after the HITL middleware so `PreToolUse` resolves before approval routing.
2887
+ from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
2873
2888
 
2874
- hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
2875
- agent_middleware.append(
2876
- ServerHooksMiddleware(cwd=hooks_cwd, mcp_tools=mcp_tools)
2877
- )
2889
+ hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
2890
+ agent_middleware.append(ServerHooksMiddleware(cwd=hooks_cwd, mcp_tools=mcp_tools))
2878
2891
 
2879
2892
  if fs_tools is not None:
2880
2893
  # `fs_tools` is an explicit allowlist here (`--allow-fs-tools all` and an