deepagents-code 0.1.25__tar.gz → 0.1.27__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 (302) hide show
  1. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/CHANGELOG.md +19 -0
  2. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/PKG-INFO +2 -1
  3. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_build_info.py +1 -1
  4. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_version.py +1 -1
  5. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/app.py +2 -3
  6. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/config.py +72 -6
  7. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/doctor.py +53 -5
  8. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_auth.py +36 -1
  9. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/server_graph.py +7 -1
  10. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/update_check.py +65 -21
  11. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/history.py +8 -2
  12. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/pyproject.toml +2 -1
  13. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/scripts/install.sh +75 -41
  14. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_app.py +5 -4
  15. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_config.py +84 -2
  16. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_doctor.py +90 -3
  17. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_history.py +101 -0
  18. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_install_script.py +142 -4
  19. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_auth.py +121 -1
  20. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_server_graph.py +11 -1
  21. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_update_check.py +127 -60
  22. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/uv.lock +3 -1
  23. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/.gitignore +0 -0
  24. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/AGENTS.md +0 -0
  25. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/ARCHITECTURE.md +0 -0
  26. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/COMMANDS.md +0 -0
  27. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/DEVELOPMENT.md +0 -0
  28. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/Makefile +0 -0
  29. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/README.md +0 -0
  30. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/THREAT_MODEL.md +0 -0
  31. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/__init__.py +0 -0
  32. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/__main__.py +0 -0
  33. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_ask_user_types.py +0 -0
  34. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_cli_context.py +0 -0
  35. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_constants.py +0 -0
  36. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_debug.py +0 -0
  37. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_env_vars.py +0 -0
  38. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_git.py +0 -0
  39. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_paths.py +0 -0
  40. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_server_config.py +0 -0
  41. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_session_stats.py +0 -0
  42. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_startup_error.py +0 -0
  43. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_testing_models.py +0 -0
  44. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/_textual_patches.py +0 -0
  45. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/agent.py +0 -0
  46. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/app.tcss +0 -0
  47. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/approval_mode.py +0 -0
  48. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/ask_user.py +0 -0
  49. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/auth_commands.py +0 -0
  50. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/auth_display.py +0 -0
  51. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/auth_store.py +0 -0
  52. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/__init__.py +0 -0
  53. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  54. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  55. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  56. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  57. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/clipboard.py +0 -0
  58. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/command_registry.py +0 -0
  59. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/config_commands.py +0 -0
  60. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/config_manifest.py +0 -0
  61. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/configurable_model.py +0 -0
  62. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/default_agent_prompt.md +0 -0
  63. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/editor.py +0 -0
  64. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/event_bus.py +0 -0
  65. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/extras_info.py +0 -0
  66. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/file_ops.py +0 -0
  67. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/formatting.py +0 -0
  68. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/hooks.py +0 -0
  69. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/input.py +0 -0
  70. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/__init__.py +0 -0
  71. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/openai_codex.py +0 -0
  72. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_config.py +0 -0
  73. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_factory.py +0 -0
  74. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_provider.py +0 -0
  75. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_registry.py +0 -0
  76. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/iterm_cursor_guide.py +0 -0
  77. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/local_context.py +0 -0
  78. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/main.py +0 -0
  79. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/managed_tools.py +0 -0
  80. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_commands.py +0 -0
  81. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_disabled.py +0 -0
  82. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_login_service.py +0 -0
  83. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_oauth_ui.py +0 -0
  84. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/__init__.py +0 -0
  85. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/_registry.py +0 -0
  86. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/base.py +0 -0
  87. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/github.py +0 -0
  88. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/slack.py +0 -0
  89. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_tools.py +0 -0
  90. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/mcp_trust.py +0 -0
  91. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/media_utils.py +0 -0
  92. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/memory_guard.py +0 -0
  93. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/model_config.py +0 -0
  94. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/non_interactive.py +0 -0
  95. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/notifications.py +0 -0
  96. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/offload.py +0 -0
  97. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/onboarding.py +0 -0
  98. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/output.py +0 -0
  99. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/project_utils.py +0 -0
  100. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/py.typed +0 -0
  101. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/remote_client.py +0 -0
  102. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/resume_state.py +0 -0
  103. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/server.py +0 -0
  104. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/server_manager.py +0 -0
  105. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/sessions.py +0 -0
  106. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/skills/__init__.py +0 -0
  107. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/skills/commands.py +0 -0
  108. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/skills/invocation.py +0 -0
  109. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/skills/load.py +0 -0
  110. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/state_migration.py +0 -0
  111. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/subagents.py +0 -0
  112. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/system_prompt.md +0 -0
  113. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/terminal_capabilities.py +0 -0
  114. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/terminal_escape.py +0 -0
  115. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/textual_adapter.py +0 -0
  116. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/theme.py +0 -0
  117. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/tool_display.py +0 -0
  118. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/tools.py +0 -0
  119. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/tools_commands.py +0 -0
  120. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/ui.py +0 -0
  121. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/unicode_security.py +0 -0
  122. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/__init__.py +0 -0
  123. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/_js_eval_display.py +0 -0
  124. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/_links.py +0 -0
  125. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/agent_selector.py +0 -0
  126. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/approval.py +0 -0
  127. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/ask_user.py +0 -0
  128. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/auth.py +0 -0
  129. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/autocomplete.py +0 -0
  130. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/chat_input.py +0 -0
  131. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/codex_auth.py +0 -0
  132. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/cwd_switch.py +0 -0
  133. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/diff.py +0 -0
  134. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/install_confirm.py +0 -0
  135. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/launch_init.py +0 -0
  136. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/loading.py +0 -0
  137. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_login.py +0 -0
  138. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_reconnect.py +0 -0
  139. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_viewer.py +0 -0
  140. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/message_store.py +0 -0
  141. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/messages.py +0 -0
  142. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/model_selector.py +0 -0
  143. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_center.py +0 -0
  144. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_detail.py +0 -0
  145. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_settings.py +0 -0
  146. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/restart_prompt.py +0 -0
  147. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/status.py +0 -0
  148. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/subagent_panel.py +0 -0
  149. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/theme_selector.py +0 -0
  150. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/thread_selector.py +0 -0
  151. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/tool_renderers.py +0 -0
  152. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/tool_widgets.py +0 -0
  153. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/update_available.py +0 -0
  154. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/update_confirm.py +0 -0
  155. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/update_progress.py +0 -0
  156. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/deepagents_code/widgets/welcome.py +0 -0
  157. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/arxiv-search/SKILL.md +0 -0
  158. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  159. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/langgraph-docs/SKILL.md +0 -0
  160. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/skill-creator/SKILL.md +0 -0
  161. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  162. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  163. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/examples/skills/web-research/SKILL.md +0 -0
  164. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/hatch_build.py +0 -0
  165. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/images/tui.png +0 -0
  166. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/scripts/check_imports.py +0 -0
  167. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/scripts/debug_server.sh +0 -0
  168. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/scripts/generate_commands_catalog.py +0 -0
  169. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/README.md +0 -0
  170. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/__init__.py +0 -0
  171. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/__init__.py +0 -0
  172. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  173. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  174. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/conftest.py +0 -0
  175. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/test_acp_mode.py +0 -0
  176. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/test_compact_resume.py +0 -0
  177. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/test_sandbox_factory.py +0 -0
  178. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/integration_tests/test_sandbox_operations.py +0 -0
  179. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/__init__.py +0 -0
  180. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/conftest.py +0 -0
  181. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/skills/__init__.py +0 -0
  182. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_commands.py +0 -0
  183. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_load.py +0 -0
  184. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_skills_json.py +0 -0
  185. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_agent.py +0 -0
  186. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_agent_friendly.py +0 -0
  187. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_agent_selector.py +0 -0
  188. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_approval.py +0 -0
  189. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_approval_mode.py +0 -0
  190. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_args.py +0 -0
  191. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_ask_user.py +0 -0
  192. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  193. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_commands.py +0 -0
  194. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_display.py +0 -0
  195. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_store.py +0 -0
  196. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_widgets.py +0 -0
  197. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_autocomplete.py +0 -0
  198. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_charset.py +0 -0
  199. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_chat_input.py +0 -0
  200. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_clipboard.py +0 -0
  201. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_command_registry.py +0 -0
  202. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_compact_tool.py +0 -0
  203. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_config_manifest.py +0 -0
  204. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_configurable_model.py +0 -0
  205. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_cursor_blink.py +0 -0
  206. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_cwd_switch.py +0 -0
  207. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_debug.py +0 -0
  208. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_editor.py +0 -0
  209. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_end_to_end.py +0 -0
  210. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_env_vars.py +0 -0
  211. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_event_bus.py +0 -0
  212. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_exception_handling.py +0 -0
  213. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_extras_info.py +0 -0
  214. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_file_ops.py +0 -0
  215. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_formatting.py +0 -0
  216. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_git.py +0 -0
  217. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_hatch_build.py +0 -0
  218. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_hooks.py +0 -0
  219. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_imports.py +0 -0
  220. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_input_parsing.py +0 -0
  221. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_install_command.py +0 -0
  222. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_install_confirm.py +0 -0
  223. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  224. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_launch_init.py +0 -0
  225. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_links.py +0 -0
  226. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_loading.py +0 -0
  227. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_local_context.py +0 -0
  228. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_main.py +0 -0
  229. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_main_acp_mode.py +0 -0
  230. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_main_args.py +0 -0
  231. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_managed_tools.py +0 -0
  232. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_commands.py +0 -0
  233. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_disabled.py +0 -0
  234. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_login_modal.py +0 -0
  235. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_login_service.py +0 -0
  236. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  237. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_reconnect.py +0 -0
  238. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_tools.py +0 -0
  239. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_trust.py +0 -0
  240. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_viewer.py +0 -0
  241. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_media_utils.py +0 -0
  242. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_memory_guard.py +0 -0
  243. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_message_store.py +0 -0
  244. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_messages.py +0 -0
  245. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_model_config.py +0 -0
  246. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_model_selector.py +0 -0
  247. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_model_switch.py +0 -0
  248. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_non_interactive.py +0 -0
  249. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_notification_center.py +0 -0
  250. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_notification_detail.py +0 -0
  251. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_notifications.py +0 -0
  252. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_offload.py +0 -0
  253. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_offload_dict_messages.py +0 -0
  254. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_onboarding.py +0 -0
  255. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  256. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_output.py +0 -0
  257. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_paths.py +0 -0
  258. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_reload.py +0 -0
  259. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_remote_client.py +0 -0
  260. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_restart_prompt.py +0 -0
  261. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_resume_state.py +0 -0
  262. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_config.py +0 -0
  263. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_factory.py +0 -0
  264. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_provider.py +0 -0
  265. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_registry.py +0 -0
  266. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_server.py +0 -0
  267. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_server_config.py +0 -0
  268. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_server_helpers.py +0 -0
  269. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_server_manager.py +0 -0
  270. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_session_stats.py +0 -0
  271. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_sessions.py +0 -0
  272. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_shell_allow_list.py +0 -0
  273. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_skill_invocation.py +0 -0
  274. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  275. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_state_migration.py +0 -0
  276. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_status.py +0 -0
  277. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_subagent_panel.py +0 -0
  278. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_subagent_stream.py +0 -0
  279. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_subagents.py +0 -0
  280. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  281. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_escape.py +0 -0
  282. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  283. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_textual_adapter.py +0 -0
  284. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_textual_patches.py +0 -0
  285. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_theme.py +0 -0
  286. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_thread_selector.py +0 -0
  287. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_tool_display.py +0 -0
  288. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_tool_renderers.py +0 -0
  289. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_tools_commands.py +0 -0
  290. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_tracing_replicas.py +0 -0
  291. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_ui.py +0 -0
  292. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_unicode_security.py +0 -0
  293. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_update_available.py +0 -0
  294. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_update_confirm.py +0 -0
  295. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_update_progress.py +0 -0
  296. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_version.py +0 -0
  297. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/test_welcome.py +0 -0
  298. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/tools/__init__.py +0 -0
  299. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/tools/test_current_thread.py +0 -0
  300. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  301. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/widgets/__init__.py +0 -0
  302. {deepagents_code-0.1.25 → deepagents_code-0.1.27}/tests/unit_tests/widgets/test_diff.py +0 -0
@@ -2,6 +2,25 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.27](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.26...deepagents-code==0.1.27) (2026-06-26)
6
+
7
+ ### Features
8
+
9
+ * Show last update check time in `dcode doctor` ([#4307](https://github.com/langchain-ai/deepagents/issues/4307)) ([b669f37](https://github.com/langchain-ai/deepagents/commit/b669f37fb08998cfbf983da76f57822215614e7b))
10
+
11
+ ### Bug Fixes
12
+
13
+ * `dcode doctor` shows `not configured` for unset tracing ([#4318](https://github.com/langchain-ai/deepagents/issues/4318)) ([e323d0c](https://github.com/langchain-ai/deepagents/commit/e323d0c7d91f3b11e03a016c14cf52008dc66b55))
14
+ * Drop duplicate token-request `client_id` under Basic auth ([#4323](https://github.com/langchain-ai/deepagents/issues/4323)) ([426dfad](https://github.com/langchain-ai/deepagents/commit/426dfad3ea1e453914cb87efa8fc70fb85a9efcb))
15
+ * Include skill invocations in input history ([#4211](https://github.com/langchain-ai/deepagents/issues/4211)) ([7b8d0b2](https://github.com/langchain-ai/deepagents/commit/7b8d0b2ec184e0d9a0cbe858a0d9a7128791969d))
16
+ * Offload `create_model` in server graph factory to unblock Codex ([#4324](https://github.com/langchain-ai/deepagents/issues/4324)) ([064ea0c](https://github.com/langchain-ai/deepagents/commit/064ea0c6851353d0b0bc347a0758149765688945))
17
+
18
+ ## [0.1.26](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.25...deepagents-code==0.1.26) (2026-06-26)
19
+
20
+ ### Bug Fixes
21
+
22
+ * Pin app version when installing extras ([#4313](https://github.com/langchain-ai/deepagents/issues/4313)) ([c20c8e2](https://github.com/langchain-ai/deepagents/commit/c20c8e2fc138f72f1444107d2a936305a591807b))
23
+
5
24
  ## [0.1.25](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.24...deepagents-code==0.1.25) (2026-06-26)
6
25
 
7
26
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-code
3
- Version: 0.1.25
3
+ Version: 0.1.27
4
4
  Summary: Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities.
5
5
  Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
6
6
  Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
@@ -45,6 +45,7 @@ Requires-Dist: mcp<2.0.0,>=1.9.2
45
45
  Requires-Dist: packaging>=26.2
46
46
  Requires-Dist: pillow<13.0.0,>=12.2.0
47
47
  Requires-Dist: prompt-toolkit<4.0.0,>=3.0.52
48
+ Requires-Dist: pydantic<2.14.0a0,>=2.7.4
48
49
  Requires-Dist: pyperclip<2.0.0,>=1.11.0
49
50
  Requires-Dist: python-dotenv<2.0.0,>=1.2.2
50
51
  Requires-Dist: pyyaml>=6.0.3
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "9f2622d"
3
+ BUILD_COMMIT = "db2fef2"
@@ -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.25" # x-release-please-version
5
+ __version__ = "0.1.27" # 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."""
@@ -9995,9 +9995,8 @@ class DeepAgentsApp(App):
9995
9995
  if not await self._prompt_model_auth_if_needed(model_spec):
9996
9996
  await self._mount_message(
9997
9997
  AppMessage(
9998
- f"Installed '{extra}'. Skipped switching to {model_spec} for "
9999
- f"nowadd credentials with `/auth`, then switch with "
10000
- f"`/model` anytime.",
9998
+ f"Installed '{extra}'. Switch to {model_spec} anytime with "
9999
+ f"`/model`you'll be prompted for credentials.",
10001
10000
  ),
10002
10001
  )
10003
10002
  return
@@ -2731,6 +2731,47 @@ def _tracing_enabled_from(env: dict[str, str]) -> bool:
2731
2731
  )
2732
2732
 
2733
2733
 
2734
+ def _tracing_explicitly_disabled_from(env: dict[str, str]) -> bool:
2735
+ """Return whether a tracing flag is explicitly set to a recognized off value.
2736
+
2737
+ True only when tracing is not enabled and at least one tracing-enable flag
2738
+ carries a falsy token (`0`/`false`/`no`/`off`). An empty flag usually reads
2739
+ as "not configured" rather than "disabled", except when an empty prefixed
2740
+ bridged flag shadows a canonical truthy flag and therefore disables tracing.
2741
+
2742
+ Args:
2743
+ env: Environment mapping to read.
2744
+ """
2745
+ from deepagents_code._env_vars import classify_env_bool
2746
+ from deepagents_code.model_config import _ENV_PREFIX
2747
+
2748
+ if _tracing_enabled_from(env):
2749
+ return False
2750
+
2751
+ def _is_off(raw: str | None) -> bool:
2752
+ if raw is None or not raw.strip():
2753
+ return False
2754
+ return classify_env_bool(raw) is False
2755
+
2756
+ def _empty_prefixed_shadow_disables(var: str) -> bool:
2757
+ prefixed = f"{_ENV_PREFIX}{var}"
2758
+ if prefixed not in env or env[prefixed].strip():
2759
+ return False
2760
+ canonical = env.get(var)
2761
+ return canonical is not None and classify_env_bool(canonical) is True
2762
+
2763
+ for var in _TRACING_BRIDGED_ENABLE_ENV_VARS:
2764
+ if _is_off(_resolve_env_var_from(env, var)) or _empty_prefixed_shadow_disables(
2765
+ var
2766
+ ):
2767
+ return True
2768
+ return any(
2769
+ _is_off(env.get(var))
2770
+ for var in _TRACING_ENABLE_ENV_VARS
2771
+ if var not in _TRACING_BRIDGED_ENABLE_ENV_VARS
2772
+ )
2773
+
2774
+
2734
2775
  def _tracing_enabled() -> bool:
2735
2776
  """Return whether tracing is (or will be) enabled, prefix-aware."""
2736
2777
  return _tracing_enabled_from(dict(os.environ))
@@ -2771,7 +2812,7 @@ def _tracing_endpoint_from(env: dict[str, str]) -> str | None:
2771
2812
  return None
2772
2813
 
2773
2814
 
2774
- def _resolve_tracing_project_from(env: dict[str, str]) -> str:
2815
+ def _resolve_tracing_project_from(env: dict[str, str]) -> tuple[str, bool]:
2775
2816
  """Resolve the project agent traces would route to, without bootstrap.
2776
2817
 
2777
2818
  The reported project matches the `tracing.langsmith_project` manifest
@@ -2784,7 +2825,8 @@ def _resolve_tracing_project_from(env: dict[str, str]) -> str:
2784
2825
  env: Environment mapping to read.
2785
2826
 
2786
2827
  Returns:
2787
- The resolved project name, or the default when none is configured.
2828
+ The resolved project name and whether it fell back to the default
2829
+ because no project was explicitly configured.
2788
2830
  """
2789
2831
  from deepagents_code._env_vars import LANGSMITH_PROJECT
2790
2832
  from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
@@ -2792,8 +2834,8 @@ def _resolve_tracing_project_from(env: dict[str, str]) -> str:
2792
2834
  for name in (LANGSMITH_PROJECT, "LANGSMITH_PROJECT"):
2793
2835
  value = env.get(name)
2794
2836
  if value:
2795
- return value
2796
- return LANGSMITH_PROJECT_DEFAULT
2837
+ return value, False
2838
+ return LANGSMITH_PROJECT_DEFAULT, True
2797
2839
 
2798
2840
 
2799
2841
  def _tracing_diagnostic_env() -> dict[str, str]:
@@ -2809,7 +2851,7 @@ def _tracing_diagnostic_env() -> dict[str, str]:
2809
2851
  return _preview_dotenv_environ(start_path=ctx.user_cwd if ctx else None)
2810
2852
 
2811
2853
 
2812
- @dataclass
2854
+ @dataclass(frozen=True)
2813
2855
  class TracingStatus:
2814
2856
  """Offline snapshot of LangSmith tracing configuration for diagnostics.
2815
2857
 
@@ -2820,6 +2862,9 @@ class TracingStatus:
2820
2862
  enabled: bool
2821
2863
  """Whether a tracing flag is truthy in the environment."""
2822
2864
 
2865
+ explicitly_disabled: bool
2866
+ """Whether a tracing flag is explicitly set to a falsy value (vs. unset)."""
2867
+
2823
2868
  has_credentials: bool
2824
2869
  """Whether an API key or profile credential is resolvable."""
2825
2870
 
@@ -2829,9 +2874,27 @@ class TracingStatus:
2829
2874
  project: str | None
2830
2875
  """Resolved configured project name, independent of active trace ingestion."""
2831
2876
 
2877
+ project_is_default: bool
2878
+ """Whether `project` is the built-in default rather than an explicit setting."""
2879
+
2832
2880
  replica_project: str | None
2833
2881
  """Extra project agent runs are mirrored to, if configured."""
2834
2882
 
2883
+ def __post_init__(self) -> None:
2884
+ """Reject the contradictory enabled/explicitly-disabled pair.
2885
+
2886
+ `enabled` and `explicitly_disabled` model a tri-state (enabled /
2887
+ explicitly disabled / not configured), so both being true is
2888
+ meaningless. Fail loud at construction rather than letting the illegal
2889
+ state flow through to the `dcode doctor` renderer.
2890
+
2891
+ Raises:
2892
+ ValueError: If both `enabled` and `explicitly_disabled` are true.
2893
+ """
2894
+ if self.enabled and self.explicitly_disabled:
2895
+ msg = "tracing cannot be both enabled and explicitly disabled"
2896
+ raise ValueError(msg)
2897
+
2835
2898
 
2836
2899
  def get_tracing_status() -> TracingStatus:
2837
2900
  """Summarize LangSmith tracing configuration for diagnostics.
@@ -2848,11 +2911,14 @@ def get_tracing_status() -> TracingStatus:
2848
2911
  enabled = _tracing_enabled_from(env)
2849
2912
  has_credentials = _tracing_has_credentials_from(env)
2850
2913
  endpoint = _tracing_endpoint_from(env)
2914
+ project, project_is_default = _resolve_tracing_project_from(env)
2851
2915
  return TracingStatus(
2852
2916
  enabled=enabled,
2917
+ explicitly_disabled=_tracing_explicitly_disabled_from(env),
2853
2918
  has_credentials=has_credentials,
2854
2919
  endpoint=endpoint,
2855
- project=_resolve_tracing_project_from(env),
2920
+ project=project,
2921
+ project_is_default=project_is_default,
2856
2922
  replica_project=_get_first_langsmith_replica_project(
2857
2923
  _get_langsmith_replica_projects_from(env)
2858
2924
  ),
@@ -23,6 +23,8 @@ from deepagents_code.output import write_json
23
23
  if TYPE_CHECKING:
24
24
  import argparse
25
25
 
26
+ from deepagents_code.config import TracingStatus
27
+
26
28
  logger = logging.getLogger(__name__)
27
29
 
28
30
 
@@ -216,11 +218,35 @@ def _collect_updates() -> DiagnosticSection:
216
218
  update_status = f"v{latest} available"
217
219
  else:
218
220
  update_status = "up to date"
219
- items.append(DiagnosticItem("Latest version", update_status))
221
+ items.extend(
222
+ (
223
+ DiagnosticItem("Latest version", update_status),
224
+ DiagnosticItem("Last checked", _format_last_checked()),
225
+ )
226
+ )
220
227
 
221
228
  return DiagnosticSection(title="Updates", items=items)
222
229
 
223
230
 
231
+ def _format_last_checked() -> str:
232
+ """Return a relative description of the last update check, or `never`.
233
+
234
+ `never` covers both the no-check-recorded case and, defensively, a stamp
235
+ that cannot be formatted. `get_last_update_check_time` only returns finite,
236
+ in-range epochs, so the formatting path does not raise here.
237
+ """
238
+ from datetime import UTC, datetime
239
+
240
+ from deepagents_code.sessions import format_relative_timestamp
241
+ from deepagents_code.update_check import get_last_update_check_time
242
+
243
+ checked_at = get_last_update_check_time()
244
+ if checked_at is None:
245
+ return "never"
246
+ iso = datetime.fromtimestamp(checked_at, tz=UTC).isoformat()
247
+ return format_relative_timestamp(iso) or "never"
248
+
249
+
224
250
  def _sanitize_endpoint(endpoint: str) -> str:
225
251
  """Return a paste-safe custom endpoint identifier.
226
252
 
@@ -248,10 +274,26 @@ def _sanitize_endpoint(endpoint: str) -> str:
248
274
  return f"{parsed.scheme}://{netloc}"
249
275
 
250
276
 
277
+ def _format_tracing_project(status: TracingStatus) -> str:
278
+ """Render the tracing project, marking the unconfigured default.
279
+
280
+ Returns:
281
+ The project name with a `(default)` suffix when it is the built-in
282
+ fallback rather than an explicit setting, or `(unset)` when absent.
283
+ """
284
+ if not status.project:
285
+ return "(unset)"
286
+ if status.project_is_default:
287
+ return f"{status.project} (default)"
288
+ return status.project
289
+
290
+
251
291
  def _collect_tracing() -> DiagnosticSection:
252
292
  """Collect LangSmith tracing status from env and profile (offline).
253
293
 
254
- Credentials are reported as configured/not configured only the API key
294
+ Tracing reads `enabled` when a flag is truthy, `disabled` only when a flag
295
+ is explicitly set to a falsy value, and `not configured` when no flag is set.
296
+ Credentials are reported as configured/not set only — the API key
255
297
  value is never read or printed. The `Credentials` item is flagged as a
256
298
  problem only when tracing is enabled without a key and without a custom
257
299
  endpoint, mirroring the runtime's orphaned-tracing guard (a keyless
@@ -264,14 +306,20 @@ def _collect_tracing() -> DiagnosticSection:
264
306
 
265
307
  status = get_tracing_status()
266
308
  creds_required = status.enabled and status.endpoint is None
309
+ if status.enabled:
310
+ tracing_value = "enabled"
311
+ elif status.explicitly_disabled:
312
+ tracing_value = "disabled"
313
+ else:
314
+ tracing_value = "not configured"
267
315
  items = [
268
- DiagnosticItem("Tracing", "enabled" if status.enabled else "disabled"),
316
+ DiagnosticItem("Tracing", tracing_value),
269
317
  DiagnosticItem(
270
318
  "Credentials",
271
- "configured" if status.has_credentials else "not configured",
319
+ "configured" if status.has_credentials else "not set",
272
320
  ok=status.has_credentials or not creds_required,
273
321
  ),
274
- DiagnosticItem("Project", status.project or "(unset)"),
322
+ DiagnosticItem("Project", _format_tracing_project(status)),
275
323
  ]
276
324
  if status.endpoint:
277
325
  items.append(DiagnosticItem("Endpoint", _sanitize_endpoint(status.endpoint)))
@@ -24,7 +24,7 @@ import stat
24
24
  import threading
25
25
  import time
26
26
  from collections.abc import AsyncGenerator, Awaitable, Callable
27
- from typing import TYPE_CHECKING, Literal, TypedDict
27
+ from typing import TYPE_CHECKING, Any, Literal, TypedDict
28
28
  from urllib.parse import parse_qs, urlparse
29
29
 
30
30
  import httpx
@@ -47,6 +47,8 @@ from pydantic import BaseModel, ConfigDict, ValidationError
47
47
  if TYPE_CHECKING:
48
48
  from pathlib import Path
49
49
 
50
+ from mcp.client.auth.oauth2 import OAuthContext
51
+
50
52
  from deepagents_code.mcp_oauth_ui import OAuthInteraction
51
53
 
52
54
 
@@ -1046,6 +1048,35 @@ def _append_query_params(url: str, params: dict[str, str]) -> str:
1046
1048
  return urlunparse(parsed._replace(query=urlencode(existing, doseq=True)))
1047
1049
 
1048
1050
 
1051
+ def _strip_duplicate_client_id_under_basic_auth(context: OAuthContext) -> None:
1052
+ """Drop the redundant body `client_id` when token auth uses HTTP Basic.
1053
+
1054
+ The MCP SDK copies `client_id` into the token-request body (on both the
1055
+ authorization-code exchange and refresh paths) and, for
1056
+ `token_endpoint_auth_method == "client_secret_basic"`, *also* sends it in the
1057
+ `Authorization: Basic` header. RFC 6749 §2.3.1 carries the client identity in
1058
+ the header for Basic auth, so the body copy is redundant; some authorization
1059
+ servers (e.g. Pylon) reject the duplicate identity with an `OAuthTokenError`.
1060
+ Wrapping `prepare_token_auth` strips the body `client_id` only when a Basic
1061
+ header is present, leaving `client_secret_post`/`none` flows untouched.
1062
+ """
1063
+ original = context.prepare_token_auth
1064
+
1065
+ def prepare_token_auth(
1066
+ data: dict[str, str],
1067
+ headers: dict[str, str] | None = None,
1068
+ ) -> tuple[dict[str, str], dict[str, str]]:
1069
+ data, headers = original(data, headers)
1070
+ # RFC 7617 makes the auth-scheme token case-insensitive, so match
1071
+ # `basic` regardless of casing rather than coupling to the SDK's exact
1072
+ # `Basic ` literal.
1073
+ if headers.get("Authorization", "").lower().startswith("basic "):
1074
+ data = {k: v for k, v in data.items() if k != "client_id"}
1075
+ return data, headers
1076
+
1077
+ context.prepare_token_auth = prepare_token_auth # ty: ignore[invalid-assignment]
1078
+
1079
+
1049
1080
  class _ExpiryAwareOAuthClientProvider(OAuthClientProvider):
1050
1081
  """`OAuthClientProvider` that restores `token_expiry_time` from storage.
1051
1082
 
@@ -1063,6 +1094,10 @@ class _ExpiryAwareOAuthClientProvider(OAuthClientProvider):
1063
1094
  falling back to 401.
1064
1095
  """
1065
1096
 
1097
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
1098
+ super().__init__(*args, **kwargs)
1099
+ _strip_duplicate_client_id_under_basic_auth(self.context)
1100
+
1066
1101
  async def _initialize(self) -> None:
1067
1102
  # Overrides a leading-underscore SDK method; behavior depends on
1068
1103
  # `super()._initialize()` populating `context.current_tokens` from
@@ -163,7 +163,13 @@ async def _make_graph() -> Any: # noqa: ANN401
163
163
  if project_context is not None:
164
164
  settings.reload_from_environment(start_path=project_context.user_cwd)
165
165
 
166
- result = create_model(config.model, extra_kwargs=config.model_params)
166
+ # Offload to a worker thread: `create_model` does blocking disk IO for some
167
+ # providers (e.g. the `openai_codex` token store currently acquires a file
168
+ # lock via `langchain-openai` that calls `os.mkdir`), which `blockbuster`
169
+ # rejects on the server event loop.
170
+ result = await asyncio.to_thread(
171
+ create_model, config.model, extra_kwargs=config.model_params
172
+ )
167
173
  result.apply_to_settings()
168
174
 
169
175
  tools, mcp_server_info = await _build_tools(config, project_context)
@@ -14,6 +14,7 @@ from __future__ import annotations
14
14
  import asyncio
15
15
  import json
16
16
  import logging
17
+ import math
17
18
  import operator
18
19
  import os
19
20
  import re
@@ -240,7 +241,8 @@ def get_cached_update_available() -> tuple[bool, str | None]:
240
241
  if not isinstance(data, dict):
241
242
  return False, None
242
243
  checked_at = data.get("checked_at")
243
- if not isinstance(checked_at, (int, float)):
244
+ checked_at = _coerce_checked_at(checked_at)
245
+ if checked_at is None:
244
246
  return False, None
245
247
  if time.time() - checked_at >= CACHE_TTL:
246
248
  return False, None
@@ -253,6 +255,42 @@ def get_cached_update_available() -> tuple[bool, str | None]:
253
255
  return False, None
254
256
 
255
257
 
258
+ def _coerce_checked_at(value: object) -> float | None:
259
+ """Return a valid epoch timestamp from cached state, or `None`."""
260
+ if not isinstance(value, (int, float)) or isinstance(value, bool):
261
+ return None
262
+ checked_at = float(value)
263
+ if not math.isfinite(checked_at):
264
+ return None
265
+ try:
266
+ datetime.fromtimestamp(checked_at, tz=UTC)
267
+ except (OverflowError, OSError, ValueError):
268
+ return None
269
+ return checked_at
270
+
271
+
272
+ def get_last_update_check_time() -> float | None:
273
+ """Return the epoch time of the last PyPI update check, or `None`.
274
+
275
+ Reads the `checked_at` stamp recorded in `CACHE_FILE` when the update cache
276
+ is written (primarily by `get_latest_version`; also seeded by
277
+ `_write_release_requires_prereleases`). Missing, corrupt, or non-numeric
278
+ data fail-soft to `None` so callers can render an "unknown" state without
279
+ contacting the network.
280
+ """
281
+ try:
282
+ if not CACHE_FILE.exists():
283
+ return None
284
+ data = json.loads(CACHE_FILE.read_text(encoding="utf-8"))
285
+ if not isinstance(data, dict):
286
+ return None
287
+ checked_at = data.get("checked_at")
288
+ except (OSError, json.JSONDecodeError, TypeError):
289
+ logger.debug("Failed to read last update check time", exc_info=True)
290
+ return None
291
+ return _coerce_checked_at(checked_at)
292
+
293
+
256
294
  def _requires_prerelease_dependency(requirements: Sequence[object] | None) -> bool:
257
295
  """Return whether any requirement specifier names a pre-release version.
258
296
 
@@ -2123,6 +2161,7 @@ def _uv_tool_install_command(
2123
2161
  Raises:
2124
2162
  ExtrasIntrospectionError: If a metadata-sourced extra name fails PEP 508
2125
2163
  validation.
2164
+ ValueError: If `version` is not PEP 440 compliant.
2126
2165
 
2127
2166
  Propagates `ToolRequirementIntrospectionError` if the uv tool receipt's
2128
2167
  interpreter or `--with` packages cannot be determined safely from the tool
@@ -2138,6 +2177,8 @@ def _uv_tool_install_command(
2138
2177
  try:
2139
2178
  requirement = _dcode_extras_requirement(extras, version=version)
2140
2179
  except ValueError as exc:
2180
+ if str(exc).startswith("Invalid deepagents-code version"):
2181
+ raise
2141
2182
  msg = f"Distribution metadata yielded an invalid extra name: {exc}"
2142
2183
  raise ExtrasIntrospectionError(msg) from exc
2143
2184
  cmd = "uv tool install --reinstall -U" if reinstall else "uv tool install -U"
@@ -2298,13 +2339,13 @@ def install_package_command(
2298
2339
 
2299
2340
  Delegates to `_uv_tool_install_command` (the same builder the extras path
2300
2341
  uses), passing the new package as a `--with` requirement. That builder folds
2301
- already-installed extras into the `deepagents-code[...]` requirement, and
2302
- preserves the uv-managed Python interpreter, the receipt's existing `--with`
2303
- packages, and the installed pre-release channel. Without this, reinstalling
2304
- to add a second package would replace the tool with a plain `deepagents-code`
2305
- (dropping extras the user added through `/install <extra>`), rebuild with
2306
- only the newest `--with` package (dropping previously configured custom
2307
- providers), or silently downgrade a pre-release install to the latest stable.
2342
+ already-installed extras into the pinned `deepagents-code[...]` requirement,
2343
+ and preserves the uv-managed Python interpreter and the receipt's existing
2344
+ `--with` packages. Without this, reinstalling to add a second package would
2345
+ replace the tool with a plain `deepagents-code` (dropping extras the user
2346
+ added through `/install <extra>`), rebuild with only the newest `--with`
2347
+ package (dropping previously configured custom providers), or silently
2348
+ downgrade when the latest stable app depends on prerelease packages.
2308
2349
 
2309
2350
  Like the extras path (`_install_extra_uv_tool_command`), passes
2310
2351
  `reinstall=True` so the upgrade rebuilds the tool environment cleanly; see
@@ -2335,8 +2376,8 @@ def install_package_command(
2335
2376
  )
2336
2377
  raise ValueError(msg)
2337
2378
  return _uv_tool_install_command(
2338
- version=None,
2339
- include_prereleases=None,
2379
+ version=__version__,
2380
+ include_prereleases=True,
2340
2381
  distribution_name=distribution_name,
2341
2382
  with_packages_to_add=(package,),
2342
2383
  reinstall=True,
@@ -2434,6 +2475,8 @@ def _install_extra_uv_tool_command(
2434
2475
  ) -> str:
2435
2476
  """Return the receipt-preserving uv command that installs one dcode extra.
2436
2477
 
2478
+ Pins the running `deepagents-code` version and allows prerelease dependency
2479
+ resolution so adding an extra cannot make uv backtrack to an older app release.
2437
2480
  Passes `reinstall=True` so the upgrade rebuilds the tool environment from
2438
2481
  scratch rather than patching it in place; see `_uv_tool_install_command`'s
2439
2482
  `reinstall` parameter for why an in-place upgrade is unsafe.
@@ -2459,8 +2502,8 @@ def _install_extra_uv_tool_command(
2459
2502
  )
2460
2503
  raise ValueError(msg)
2461
2504
  return _uv_tool_install_command(
2462
- version=None,
2463
- include_prereleases=None,
2505
+ version=__version__,
2506
+ include_prereleases=True,
2464
2507
  distribution_name=distribution_name,
2465
2508
  extras_to_add=(extra,),
2466
2509
  reinstall=True,
@@ -2504,11 +2547,11 @@ async def perform_install_extra(
2504
2547
  ) -> tuple[bool, str]:
2505
2548
  """Add `extra` to the installed dcode tool environment.
2506
2549
 
2507
- Runs `uv tool install --reinstall -U 'deepagents-code[<extras>]'`,
2508
- preserving any extras that are already installed. Editable installs are
2509
- refused — the caller should rerun their `uv tool install --editable` command
2510
- with `--with 'deepagents-code[<extra>]'` added so the extra is resolved
2511
- against the editable source.
2550
+ Runs `uv tool install --reinstall -U 'deepagents-code[<extras>]==<current>'
2551
+ --prerelease allow`, preserving any extras that are already installed.
2552
+ Editable installs are refused — the caller should rerun their
2553
+ `uv tool install --editable` command with `--with 'deepagents-code[<extra>]'`
2554
+ added so the extra is resolved against the editable source.
2512
2555
 
2513
2556
  Args:
2514
2557
  extra: The extra name to install. Must satisfy `is_valid_extra_name`;
@@ -2575,10 +2618,11 @@ async def perform_install_package(
2575
2618
  ) -> tuple[bool, str]:
2576
2619
  """Add an arbitrary `package` to the installed dcode tool environment.
2577
2620
 
2578
- Runs `uv tool install --reinstall -U 'deepagents-code[<extras>]' --with
2579
- <package>`, the escape hatch for a provider whose package is not a
2580
- `deepagents-code` extra (e.g. a custom or in-house `class_path` model).
2581
- Already-installed extras are preserved so the reinstall does not drop them.
2621
+ Runs `uv tool install --reinstall -U 'deepagents-code[<extras>]==<current>'
2622
+ --with <package> --prerelease allow`, the escape hatch for a provider whose
2623
+ package is not a `deepagents-code` extra (e.g. a custom or in-house
2624
+ `class_path` model). Already-installed extras are preserved so the reinstall
2625
+ does not drop them.
2582
2626
  Editable installs are refused
2583
2627
  — the caller should rerun their `uv tool install --editable` command with
2584
2628
  `--with <package>` added so it resolves against the editable source.
@@ -97,8 +97,14 @@ class HistoryManager:
97
97
  text: The command text to add
98
98
  """
99
99
  text = text.strip()
100
- # Skip empty or slash commands
101
- if not text or text.startswith("/"):
100
+ # Skip empty input and slash commands, except the explicit
101
+ # `/skill:<name>` form (case-insensitive), which is kept so users can
102
+ # recall it with up-arrow. Note: history stores the raw submitted text
103
+ # *before* app-layer alias rewriting, so convenience aliases such as
104
+ # `/remember` (later rewritten to `/skill:remember`) are dropped here
105
+ # despite being skill invocations.
106
+ lower_text = text.lower()
107
+ if not text or (text.startswith("/") and not lower_text.startswith("/skill:")):
102
108
  return
103
109
 
104
110
  # Skip duplicates of the last entry
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "deepagents-code"
7
- version = "0.1.25"
7
+ version = "0.1.27"
8
8
  description = "Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -40,6 +40,7 @@ dependencies = [
40
40
  "langchain-anthropic>=1.4.7,<2.0.0",
41
41
  "langchain-google-genai>=4.2.5,<5.0.0",
42
42
  "langchain-openai>=1.3.3,<2.0.0",
43
+ "pydantic>=2.7.4,<2.14.0a0",
43
44
 
44
45
  # UI/Terminal
45
46
  # Workaround for Textualize/textual#6378 lives in `_textual_patches.py`.