deepagents-code 0.1.26__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.26 → deepagents_code-0.1.27}/CHANGELOG.md +13 -0
  2. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/PKG-INFO +1 -1
  3. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_build_info.py +1 -1
  4. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_version.py +1 -1
  5. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/app.py +2 -3
  6. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/config.py +72 -6
  7. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/doctor.py +53 -5
  8. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_auth.py +36 -1
  9. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/server_graph.py +7 -1
  10. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/update_check.py +39 -1
  11. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/history.py +8 -2
  12. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/pyproject.toml +1 -1
  13. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_app.py +1 -1
  14. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_config.py +80 -0
  15. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_doctor.py +90 -3
  16. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_history.py +101 -0
  17. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_auth.py +121 -1
  18. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_server_graph.py +11 -1
  19. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_update_check.py +48 -0
  20. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/uv.lock +1 -1
  21. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/.gitignore +0 -0
  22. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/AGENTS.md +0 -0
  23. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/ARCHITECTURE.md +0 -0
  24. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/COMMANDS.md +0 -0
  25. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/DEVELOPMENT.md +0 -0
  26. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/Makefile +0 -0
  27. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/README.md +0 -0
  28. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/THREAT_MODEL.md +0 -0
  29. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/__init__.py +0 -0
  30. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/__main__.py +0 -0
  31. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_ask_user_types.py +0 -0
  32. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_cli_context.py +0 -0
  33. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_constants.py +0 -0
  34. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_debug.py +0 -0
  35. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_env_vars.py +0 -0
  36. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_git.py +0 -0
  37. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_paths.py +0 -0
  38. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_server_config.py +0 -0
  39. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_session_stats.py +0 -0
  40. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_startup_error.py +0 -0
  41. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_testing_models.py +0 -0
  42. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/_textual_patches.py +0 -0
  43. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/agent.py +0 -0
  44. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/app.tcss +0 -0
  45. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/approval_mode.py +0 -0
  46. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/ask_user.py +0 -0
  47. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/auth_commands.py +0 -0
  48. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/auth_display.py +0 -0
  49. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/auth_store.py +0 -0
  50. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/__init__.py +0 -0
  51. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  52. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  53. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  54. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  55. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/clipboard.py +0 -0
  56. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/command_registry.py +0 -0
  57. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/config_commands.py +0 -0
  58. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/config_manifest.py +0 -0
  59. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/configurable_model.py +0 -0
  60. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/default_agent_prompt.md +0 -0
  61. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/editor.py +0 -0
  62. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/event_bus.py +0 -0
  63. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/extras_info.py +0 -0
  64. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/file_ops.py +0 -0
  65. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/formatting.py +0 -0
  66. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/hooks.py +0 -0
  67. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/input.py +0 -0
  68. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/__init__.py +0 -0
  69. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/openai_codex.py +0 -0
  70. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_config.py +0 -0
  71. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_factory.py +0 -0
  72. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_provider.py +0 -0
  73. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/integrations/sandbox_registry.py +0 -0
  74. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/iterm_cursor_guide.py +0 -0
  75. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/local_context.py +0 -0
  76. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/main.py +0 -0
  77. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/managed_tools.py +0 -0
  78. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_commands.py +0 -0
  79. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_disabled.py +0 -0
  80. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_login_service.py +0 -0
  81. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_oauth_ui.py +0 -0
  82. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/__init__.py +0 -0
  83. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/_registry.py +0 -0
  84. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/base.py +0 -0
  85. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/github.py +0 -0
  86. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_providers/slack.py +0 -0
  87. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_tools.py +0 -0
  88. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/mcp_trust.py +0 -0
  89. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/media_utils.py +0 -0
  90. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/memory_guard.py +0 -0
  91. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/model_config.py +0 -0
  92. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/non_interactive.py +0 -0
  93. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/notifications.py +0 -0
  94. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/offload.py +0 -0
  95. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/onboarding.py +0 -0
  96. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/output.py +0 -0
  97. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/project_utils.py +0 -0
  98. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/py.typed +0 -0
  99. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/remote_client.py +0 -0
  100. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/resume_state.py +0 -0
  101. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/server.py +0 -0
  102. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/server_manager.py +0 -0
  103. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/sessions.py +0 -0
  104. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/skills/__init__.py +0 -0
  105. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/skills/commands.py +0 -0
  106. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/skills/invocation.py +0 -0
  107. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/skills/load.py +0 -0
  108. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/state_migration.py +0 -0
  109. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/subagents.py +0 -0
  110. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/system_prompt.md +0 -0
  111. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/terminal_capabilities.py +0 -0
  112. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/terminal_escape.py +0 -0
  113. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/textual_adapter.py +0 -0
  114. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/theme.py +0 -0
  115. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/tool_display.py +0 -0
  116. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/tools.py +0 -0
  117. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/tools_commands.py +0 -0
  118. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/ui.py +0 -0
  119. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/unicode_security.py +0 -0
  120. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/__init__.py +0 -0
  121. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/_js_eval_display.py +0 -0
  122. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/_links.py +0 -0
  123. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/agent_selector.py +0 -0
  124. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/approval.py +0 -0
  125. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/ask_user.py +0 -0
  126. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/auth.py +0 -0
  127. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/autocomplete.py +0 -0
  128. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/chat_input.py +0 -0
  129. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/codex_auth.py +0 -0
  130. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/cwd_switch.py +0 -0
  131. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/diff.py +0 -0
  132. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/install_confirm.py +0 -0
  133. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/launch_init.py +0 -0
  134. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/loading.py +0 -0
  135. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_login.py +0 -0
  136. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_reconnect.py +0 -0
  137. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/mcp_viewer.py +0 -0
  138. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/message_store.py +0 -0
  139. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/messages.py +0 -0
  140. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/model_selector.py +0 -0
  141. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_center.py +0 -0
  142. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_detail.py +0 -0
  143. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/notification_settings.py +0 -0
  144. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/restart_prompt.py +0 -0
  145. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/status.py +0 -0
  146. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/subagent_panel.py +0 -0
  147. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/theme_selector.py +0 -0
  148. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/thread_selector.py +0 -0
  149. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/tool_renderers.py +0 -0
  150. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/tool_widgets.py +0 -0
  151. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/update_available.py +0 -0
  152. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/update_confirm.py +0 -0
  153. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/update_progress.py +0 -0
  154. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/deepagents_code/widgets/welcome.py +0 -0
  155. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/arxiv-search/SKILL.md +0 -0
  156. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  157. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/langgraph-docs/SKILL.md +0 -0
  158. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/skill-creator/SKILL.md +0 -0
  159. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  160. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  161. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/examples/skills/web-research/SKILL.md +0 -0
  162. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/hatch_build.py +0 -0
  163. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/images/tui.png +0 -0
  164. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/scripts/check_imports.py +0 -0
  165. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/scripts/debug_server.sh +0 -0
  166. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/scripts/generate_commands_catalog.py +0 -0
  167. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/scripts/install.sh +0 -0
  168. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/README.md +0 -0
  169. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/__init__.py +0 -0
  170. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/__init__.py +0 -0
  171. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  172. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  173. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/conftest.py +0 -0
  174. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/test_acp_mode.py +0 -0
  175. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/test_compact_resume.py +0 -0
  176. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/test_sandbox_factory.py +0 -0
  177. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/integration_tests/test_sandbox_operations.py +0 -0
  178. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/__init__.py +0 -0
  179. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/conftest.py +0 -0
  180. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/skills/__init__.py +0 -0
  181. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_commands.py +0 -0
  182. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_load.py +0 -0
  183. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/skills/test_skills_json.py +0 -0
  184. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_agent.py +0 -0
  185. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_agent_friendly.py +0 -0
  186. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_agent_selector.py +0 -0
  187. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_approval.py +0 -0
  188. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_approval_mode.py +0 -0
  189. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_args.py +0 -0
  190. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_ask_user.py +0 -0
  191. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  192. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_commands.py +0 -0
  193. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_display.py +0 -0
  194. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_store.py +0 -0
  195. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_auth_widgets.py +0 -0
  196. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_autocomplete.py +0 -0
  197. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_charset.py +0 -0
  198. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_chat_input.py +0 -0
  199. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_clipboard.py +0 -0
  200. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_command_registry.py +0 -0
  201. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_compact_tool.py +0 -0
  202. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_config_manifest.py +0 -0
  203. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_configurable_model.py +0 -0
  204. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_cursor_blink.py +0 -0
  205. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_cwd_switch.py +0 -0
  206. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_debug.py +0 -0
  207. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_editor.py +0 -0
  208. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_end_to_end.py +0 -0
  209. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_env_vars.py +0 -0
  210. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_event_bus.py +0 -0
  211. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_exception_handling.py +0 -0
  212. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_extras_info.py +0 -0
  213. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_file_ops.py +0 -0
  214. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_formatting.py +0 -0
  215. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_git.py +0 -0
  216. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_hatch_build.py +0 -0
  217. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_hooks.py +0 -0
  218. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_imports.py +0 -0
  219. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_input_parsing.py +0 -0
  220. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_install_command.py +0 -0
  221. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_install_confirm.py +0 -0
  222. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_install_script.py +0 -0
  223. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  224. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_launch_init.py +0 -0
  225. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_links.py +0 -0
  226. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_loading.py +0 -0
  227. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_local_context.py +0 -0
  228. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_main.py +0 -0
  229. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_main_acp_mode.py +0 -0
  230. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_main_args.py +0 -0
  231. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_managed_tools.py +0 -0
  232. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_commands.py +0 -0
  233. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_disabled.py +0 -0
  234. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_login_modal.py +0 -0
  235. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_login_service.py +0 -0
  236. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  237. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_reconnect.py +0 -0
  238. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_tools.py +0 -0
  239. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_trust.py +0 -0
  240. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_mcp_viewer.py +0 -0
  241. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_media_utils.py +0 -0
  242. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_memory_guard.py +0 -0
  243. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_message_store.py +0 -0
  244. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_messages.py +0 -0
  245. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_model_config.py +0 -0
  246. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_model_selector.py +0 -0
  247. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_model_switch.py +0 -0
  248. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_non_interactive.py +0 -0
  249. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_notification_center.py +0 -0
  250. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_notification_detail.py +0 -0
  251. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_notifications.py +0 -0
  252. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_offload.py +0 -0
  253. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_offload_dict_messages.py +0 -0
  254. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_onboarding.py +0 -0
  255. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  256. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_output.py +0 -0
  257. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_paths.py +0 -0
  258. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_reload.py +0 -0
  259. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_remote_client.py +0 -0
  260. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_restart_prompt.py +0 -0
  261. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_resume_state.py +0 -0
  262. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_config.py +0 -0
  263. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_factory.py +0 -0
  264. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_provider.py +0 -0
  265. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_sandbox_registry.py +0 -0
  266. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_server.py +0 -0
  267. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_server_config.py +0 -0
  268. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_server_helpers.py +0 -0
  269. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_server_manager.py +0 -0
  270. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_session_stats.py +0 -0
  271. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_sessions.py +0 -0
  272. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_shell_allow_list.py +0 -0
  273. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_skill_invocation.py +0 -0
  274. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  275. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_state_migration.py +0 -0
  276. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_status.py +0 -0
  277. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_subagent_panel.py +0 -0
  278. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_subagent_stream.py +0 -0
  279. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_subagents.py +0 -0
  280. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  281. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_escape.py +0 -0
  282. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  283. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_textual_adapter.py +0 -0
  284. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_textual_patches.py +0 -0
  285. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_theme.py +0 -0
  286. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_thread_selector.py +0 -0
  287. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_tool_display.py +0 -0
  288. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_tool_renderers.py +0 -0
  289. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_tools_commands.py +0 -0
  290. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_tracing_replicas.py +0 -0
  291. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_ui.py +0 -0
  292. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_unicode_security.py +0 -0
  293. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_update_available.py +0 -0
  294. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_update_confirm.py +0 -0
  295. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_update_progress.py +0 -0
  296. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_version.py +0 -0
  297. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/test_welcome.py +0 -0
  298. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/tools/__init__.py +0 -0
  299. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/tools/test_current_thread.py +0 -0
  300. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  301. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/widgets/__init__.py +0 -0
  302. {deepagents_code-0.1.26 → deepagents_code-0.1.27}/tests/unit_tests/widgets/test_diff.py +0 -0
@@ -2,6 +2,19 @@
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
+
5
18
  ## [0.1.26](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.25...deepagents-code==0.1.26) (2026-06-26)
6
19
 
7
20
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-code
3
- Version: 0.1.26
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/
@@ -1,3 +1,3 @@
1
1
  """Generated at build time. Do not edit or commit."""
2
2
 
3
- BUILD_COMMIT = "de6e341"
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.26" # 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
 
@@ -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.26"
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" }
@@ -8012,8 +8012,8 @@ class TestInstallExtraModelSwitch:
8012
8012
  for c in app._mount_message.await_args_list # ty: ignore
8013
8013
  )
8014
8014
  assert "Installed" in mounted
8015
- assert "/auth" in mounted
8016
8015
  assert "/model" in mounted
8016
+ assert "prompted for credentials" in mounted
8017
8017
 
8018
8018
  async def test_install_extra_auto_restart_skips_restart_for_deferred_startup(
8019
8019
  self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
@@ -2333,11 +2333,56 @@ class TestGetTracingStatus:
2333
2333
  with patch.dict("os.environ", self._CLEAN, clear=False):
2334
2334
  status = get_tracing_status()
2335
2335
  assert status.enabled is False
2336
+ assert status.explicitly_disabled is False
2336
2337
  assert status.has_credentials is False
2337
2338
  assert status.endpoint is None
2338
2339
  assert status.project == LANGSMITH_PROJECT_DEFAULT
2340
+ assert status.project_is_default is True
2339
2341
  assert status.replica_project is None
2340
2342
 
2343
+ @pytest.mark.parametrize(
2344
+ ("var", "token", "expected_enabled", "expected_disabled"),
2345
+ [
2346
+ # Non-bridged flags (bare `env.get` path) set to each falsy token.
2347
+ ("LANGSMITH_TRACING_V2", "false", False, True),
2348
+ ("LANGSMITH_TRACING_V2", "0", False, True),
2349
+ ("LANGSMITH_TRACING_V2", "no", False, True),
2350
+ ("LANGSMITH_TRACING_V2", "off", False, True),
2351
+ ("LANGCHAIN_TRACING", "false", False, True),
2352
+ # Prefixed bridged falsy flag — exercises the prefix-aware
2353
+ # `_resolve_env_var_from` off path; doctor runs pre-bootstrap.
2354
+ ("DEEPAGENTS_CODE_LANGSMITH_TRACING", "false", False, True),
2355
+ # An empty flag reads as not configured, not an explicit opt-out.
2356
+ ("LANGSMITH_TRACING_V2", "", False, False),
2357
+ # An unrecognized token is neither enabled nor an explicit opt-out.
2358
+ ("LANGSMITH_TRACING_V2", "maybe", False, False),
2359
+ # A truthy flag is enabled and never reported as explicitly disabled.
2360
+ ("LANGSMITH_TRACING_V2", "true", True, False),
2361
+ ],
2362
+ )
2363
+ def test_explicit_disable_matrix(
2364
+ self,
2365
+ var: str,
2366
+ token: str,
2367
+ expected_enabled: bool,
2368
+ expected_disabled: bool,
2369
+ ) -> None:
2370
+ """Each flag/token combination resolves to the right tri-state.
2371
+
2372
+ Exercises both the bare-`env.get` path (non-bridged vars) and the
2373
+ prefix-aware `_resolve_env_var_from` path (the prefixed bridged flag),
2374
+ across every recognized falsy token plus the empty and unrecognized
2375
+ cases.
2376
+ """
2377
+ from deepagents_code.config import get_tracing_status
2378
+
2379
+ env = dict(self._CLEAN)
2380
+ env[var] = token
2381
+ with patch.dict("os.environ", env, clear=False):
2382
+ status = get_tracing_status()
2383
+ assert status.enabled is expected_enabled
2384
+ assert status.explicitly_disabled is expected_disabled
2385
+
2341
2386
  def test_prefixed_flag_and_key_are_detected(self) -> None:
2342
2387
  """`DEEPAGENTS_CODE_`-prefixed tracing/key vars resolve like the runtime.
2343
2388
 
@@ -2356,6 +2401,24 @@ class TestGetTracingStatus:
2356
2401
  assert status.enabled is True
2357
2402
  assert status.has_credentials is True
2358
2403
  assert status.project == "prefixed-proj"
2404
+ assert status.project_is_default is False
2405
+
2406
+ def test_explicit_default_name_is_not_marked_default(self) -> None:
2407
+ """Explicitly setting the default name still counts as configured.
2408
+
2409
+ `project_is_default` tracks provenance (was anything set), not a string
2410
+ match against the default. A user who sets the project to the same name
2411
+ as the built-in default must not get the `(default)` marker.
2412
+ """
2413
+ from deepagents_code.config import get_tracing_status
2414
+ from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
2415
+
2416
+ env = dict(self._CLEAN)
2417
+ env["DEEPAGENTS_CODE_LANGSMITH_PROJECT"] = LANGSMITH_PROJECT_DEFAULT
2418
+ with patch.dict("os.environ", env, clear=False):
2419
+ status = get_tracing_status()
2420
+ assert status.project == LANGSMITH_PROJECT_DEFAULT
2421
+ assert status.project_is_default is False
2359
2422
 
2360
2423
  def test_dotenv_values_are_detected(
2361
2424
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
@@ -2442,6 +2505,7 @@ class TestGetTracingStatus:
2442
2505
  with patch.dict("os.environ", env, clear=False):
2443
2506
  status = get_tracing_status()
2444
2507
  assert status.enabled is False
2508
+ assert status.explicitly_disabled is True
2445
2509
 
2446
2510
  def test_canonical_non_bridged_flag_enables(self) -> None:
2447
2511
  """A canonical, non-bridged flag (`LANGSMITH_TRACING_V2`) enables tracing."""
@@ -2517,6 +2581,7 @@ class TestGetTracingStatus:
2517
2581
  with patch.dict("os.environ", env, clear=False):
2518
2582
  status = get_tracing_status()
2519
2583
  assert status.project == "prod"
2584
+ assert status.project_is_default is False
2520
2585
 
2521
2586
  def test_reports_first_replica_project(self) -> None:
2522
2587
  """Only the first replica project is reported (server mirrors one)."""
@@ -2528,6 +2593,21 @@ class TestGetTracingStatus:
2528
2593
  status = get_tracing_status()
2529
2594
  assert status.replica_project == "replica-a"
2530
2595
 
2596
+ def test_enabled_and_explicitly_disabled_is_rejected(self) -> None:
2597
+ """The contradictory enabled/disabled pair fails loud at construction."""
2598
+ from deepagents_code.config import TracingStatus
2599
+
2600
+ with pytest.raises(ValueError, match="both enabled and explicitly disabled"):
2601
+ TracingStatus(
2602
+ enabled=True,
2603
+ explicitly_disabled=True,
2604
+ has_credentials=False,
2605
+ endpoint=None,
2606
+ project=None,
2607
+ project_is_default=False,
2608
+ replica_project=None,
2609
+ )
2610
+
2531
2611
 
2532
2612
  class TestQuietSdkTracingLogging:
2533
2613
  """Tests for _quiet_sdk_tracing_logging()."""