deepagents-code 0.1.17__tar.gz → 0.1.19__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 (286) hide show
  1. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/AGENTS.md +2 -1
  2. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/CHANGELOG.md +19 -0
  3. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/PKG-INFO +2 -2
  4. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_env_vars.py +19 -0
  5. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_version.py +1 -1
  6. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/app.py +335 -69
  7. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/auth_display.py +3 -3
  8. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/config.py +59 -0
  9. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/config_manifest.py +72 -0
  10. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/model_config.py +63 -0
  11. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/remote_client.py +16 -0
  12. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/auth.py +431 -53
  13. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/codex_auth.py +11 -2
  14. deepagents_code-0.1.19/deepagents_code/widgets/install_confirm.py +233 -0
  15. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/mcp_login.py +13 -0
  16. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/messages.py +76 -0
  17. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/model_selector.py +173 -29
  18. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/thread_selector.py +17 -1
  19. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/welcome.py +133 -30
  20. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/pyproject.toml +3 -3
  21. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/scripts/install.sh +3 -6
  22. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_app.py +539 -7
  23. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_auth_display.py +4 -2
  24. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_auth_widgets.py +494 -11
  25. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_config_manifest.py +53 -9
  26. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_install_command.py +127 -17
  27. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_install_confirm.py +61 -1
  28. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_login_modal.py +41 -0
  29. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_messages.py +137 -0
  30. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_model_config.py +67 -0
  31. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_model_selector.py +252 -0
  32. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_remote_client.py +67 -0
  33. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_thread_selector.py +29 -0
  34. deepagents_code-0.1.19/tests/unit_tests/test_tracing_replicas.py +70 -0
  35. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_welcome.py +170 -12
  36. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/uv.lock +161 -161
  37. deepagents_code-0.1.17/deepagents_code/widgets/install_confirm.py +0 -120
  38. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/.gitignore +0 -0
  39. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/COMMANDS.md +0 -0
  40. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/DEV.md +0 -0
  41. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/Makefile +0 -0
  42. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/README.md +0 -0
  43. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/THREAT_MODEL.md +0 -0
  44. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/__init__.py +0 -0
  45. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/__main__.py +0 -0
  46. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_ask_user_types.py +0 -0
  47. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_cli_context.py +0 -0
  48. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_constants.py +0 -0
  49. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_debug.py +0 -0
  50. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_git.py +0 -0
  51. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_server_config.py +0 -0
  52. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_session_stats.py +0 -0
  53. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_startup_error.py +0 -0
  54. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_testing_models.py +0 -0
  55. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/_textual_patches.py +0 -0
  56. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/agent.py +0 -0
  57. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/app.tcss +0 -0
  58. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/ask_user.py +0 -0
  59. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/auth_commands.py +0 -0
  60. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/auth_store.py +0 -0
  61. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/built_in_skills/__init__.py +0 -0
  62. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
  63. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
  64. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
  65. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
  66. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/clipboard.py +0 -0
  67. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/command_registry.py +0 -0
  68. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/config_commands.py +0 -0
  69. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/configurable_model.py +0 -0
  70. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/default_agent_prompt.md +0 -0
  71. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/editor.py +0 -0
  72. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/event_bus.py +0 -0
  73. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/extras_info.py +0 -0
  74. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/file_ops.py +0 -0
  75. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/filesystem_empty_result.py +0 -0
  76. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/formatting.py +0 -0
  77. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/hooks.py +0 -0
  78. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/input.py +0 -0
  79. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/__init__.py +0 -0
  80. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/openai_codex.py +0 -0
  81. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/sandbox_config.py +0 -0
  82. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/sandbox_factory.py +0 -0
  83. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/sandbox_provider.py +0 -0
  84. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/integrations/sandbox_registry.py +0 -0
  85. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/iterm_cursor_guide.py +0 -0
  86. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/local_context.py +0 -0
  87. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/main.py +0 -0
  88. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/managed_tools.py +0 -0
  89. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_auth.py +0 -0
  90. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_commands.py +0 -0
  91. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_disabled.py +0 -0
  92. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_login_service.py +0 -0
  93. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_oauth_ui.py +0 -0
  94. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_providers/__init__.py +0 -0
  95. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_providers/_registry.py +0 -0
  96. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_providers/base.py +0 -0
  97. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_providers/github.py +0 -0
  98. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_providers/slack.py +0 -0
  99. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_tools.py +0 -0
  100. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/mcp_trust.py +0 -0
  101. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/media_utils.py +0 -0
  102. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/memory_guard.py +0 -0
  103. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/non_interactive.py +0 -0
  104. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/notifications.py +0 -0
  105. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/offload.py +0 -0
  106. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/onboarding.py +0 -0
  107. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/output.py +0 -0
  108. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/project_utils.py +0 -0
  109. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/py.typed +0 -0
  110. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/resume_state.py +0 -0
  111. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/server.py +0 -0
  112. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/server_graph.py +0 -0
  113. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/server_manager.py +0 -0
  114. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/sessions.py +0 -0
  115. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/skills/__init__.py +0 -0
  116. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/skills/commands.py +0 -0
  117. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/skills/invocation.py +0 -0
  118. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/skills/load.py +0 -0
  119. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/state_migration.py +0 -0
  120. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/subagents.py +0 -0
  121. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/system_prompt.md +0 -0
  122. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/terminal_capabilities.py +0 -0
  123. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/terminal_escape.py +0 -0
  124. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/textual_adapter.py +0 -0
  125. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/theme.py +0 -0
  126. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/tool_display.py +0 -0
  127. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/tools.py +0 -0
  128. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/ui.py +0 -0
  129. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/unicode_security.py +0 -0
  130. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/update_check.py +0 -0
  131. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/__init__.py +0 -0
  132. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/_links.py +0 -0
  133. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/agent_selector.py +0 -0
  134. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/approval.py +0 -0
  135. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/ask_user.py +0 -0
  136. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/autocomplete.py +0 -0
  137. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/chat_input.py +0 -0
  138. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/cwd_switch.py +0 -0
  139. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/diff.py +0 -0
  140. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/history.py +0 -0
  141. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/launch_init.py +0 -0
  142. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/loading.py +0 -0
  143. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/mcp_reconnect.py +0 -0
  144. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/mcp_viewer.py +0 -0
  145. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/message_store.py +0 -0
  146. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/notification_center.py +0 -0
  147. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/notification_detail.py +0 -0
  148. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/notification_settings.py +0 -0
  149. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/restart_prompt.py +0 -0
  150. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/status.py +0 -0
  151. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/theme_selector.py +0 -0
  152. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/tool_renderers.py +0 -0
  153. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/tool_widgets.py +0 -0
  154. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/update_available.py +0 -0
  155. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/deepagents_code/widgets/update_progress.py +0 -0
  156. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/arxiv-search/SKILL.md +0 -0
  157. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  158. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/langgraph-docs/SKILL.md +0 -0
  159. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/skill-creator/SKILL.md +0 -0
  160. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  161. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  162. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/examples/skills/web-research/SKILL.md +0 -0
  163. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/images/tui.png +0 -0
  164. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/scripts/check_imports.py +0 -0
  165. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/scripts/debug_server.sh +0 -0
  166. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/scripts/generate_commands_catalog.py +0 -0
  167. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/README.md +0 -0
  168. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/__init__.py +0 -0
  169. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/benchmarks/__init__.py +0 -0
  170. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
  171. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
  172. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/conftest.py +0 -0
  173. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/test_acp_mode.py +0 -0
  174. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/test_compact_resume.py +0 -0
  175. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/test_sandbox_factory.py +0 -0
  176. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/integration_tests/test_sandbox_operations.py +0 -0
  177. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/__init__.py +0 -0
  178. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/conftest.py +0 -0
  179. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/skills/__init__.py +0 -0
  180. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/skills/test_commands.py +0 -0
  181. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/skills/test_load.py +0 -0
  182. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/skills/test_skills_json.py +0 -0
  183. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_agent.py +0 -0
  184. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_agent_friendly.py +0 -0
  185. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_agent_selector.py +0 -0
  186. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_approval.py +0 -0
  187. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_args.py +0 -0
  188. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_ask_user.py +0 -0
  189. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_ask_user_middleware.py +0 -0
  190. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_auth_commands.py +0 -0
  191. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_auth_store.py +0 -0
  192. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_autocomplete.py +0 -0
  193. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_charset.py +0 -0
  194. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_chat_input.py +0 -0
  195. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_clipboard.py +0 -0
  196. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_command_registry.py +0 -0
  197. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_compact_tool.py +0 -0
  198. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_config.py +0 -0
  199. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_configurable_model.py +0 -0
  200. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_cursor_blink.py +0 -0
  201. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_cwd_switch.py +0 -0
  202. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_debug.py +0 -0
  203. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_editor.py +0 -0
  204. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_end_to_end.py +0 -0
  205. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_env_vars.py +0 -0
  206. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_event_bus.py +0 -0
  207. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_exception_handling.py +0 -0
  208. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_extras_info.py +0 -0
  209. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_file_ops.py +0 -0
  210. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_filesystem_empty_result.py +0 -0
  211. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_formatting.py +0 -0
  212. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_git.py +0 -0
  213. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_history.py +0 -0
  214. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_hooks.py +0 -0
  215. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_imports.py +0 -0
  216. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_input_parsing.py +0 -0
  217. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_install_script.py +0 -0
  218. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
  219. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_launch_init.py +0 -0
  220. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_links.py +0 -0
  221. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_loading.py +0 -0
  222. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_local_context.py +0 -0
  223. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_main.py +0 -0
  224. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_main_acp_mode.py +0 -0
  225. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_main_args.py +0 -0
  226. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_managed_tools.py +0 -0
  227. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_auth.py +0 -0
  228. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_commands.py +0 -0
  229. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_disabled.py +0 -0
  230. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_login_service.py +0 -0
  231. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
  232. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_reconnect.py +0 -0
  233. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_tools.py +0 -0
  234. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_trust.py +0 -0
  235. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_mcp_viewer.py +0 -0
  236. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_media_utils.py +0 -0
  237. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_memory_guard.py +0 -0
  238. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_message_store.py +0 -0
  239. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_model_switch.py +0 -0
  240. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_non_interactive.py +0 -0
  241. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_notification_center.py +0 -0
  242. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_notification_detail.py +0 -0
  243. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_notifications.py +0 -0
  244. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_offload.py +0 -0
  245. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_offload_dict_messages.py +0 -0
  246. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_onboarding.py +0 -0
  247. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_openai_codex_integration.py +0 -0
  248. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_output.py +0 -0
  249. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_reload.py +0 -0
  250. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_restart_prompt.py +0 -0
  251. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_resume_state.py +0 -0
  252. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_sandbox_config.py +0 -0
  253. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_sandbox_factory.py +0 -0
  254. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_sandbox_provider.py +0 -0
  255. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_sandbox_registry.py +0 -0
  256. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_server.py +0 -0
  257. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_server_config.py +0 -0
  258. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_server_graph.py +0 -0
  259. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_server_helpers.py +0 -0
  260. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_server_manager.py +0 -0
  261. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_session_stats.py +0 -0
  262. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_sessions.py +0 -0
  263. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_shell_allow_list.py +0 -0
  264. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_skill_invocation.py +0 -0
  265. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_startup_fast_paths.py +0 -0
  266. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_state_migration.py +0 -0
  267. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_status.py +0 -0
  268. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_subagents.py +0 -0
  269. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_terminal_capabilities.py +0 -0
  270. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_terminal_escape.py +0 -0
  271. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
  272. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_textual_adapter.py +0 -0
  273. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_textual_patches.py +0 -0
  274. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_theme.py +0 -0
  275. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_tool_display.py +0 -0
  276. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_ui.py +0 -0
  277. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_unicode_security.py +0 -0
  278. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_update_available.py +0 -0
  279. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_update_check.py +0 -0
  280. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_update_progress.py +0 -0
  281. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/test_version.py +0 -0
  282. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/tools/__init__.py +0 -0
  283. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/tools/test_current_thread.py +0 -0
  284. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/tools/test_fetch_url.py +0 -0
  285. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/widgets/__init__.py +0 -0
  286. {deepagents_code-0.1.17 → deepagents_code-0.1.19}/tests/unit_tests/widgets/test_diff.py +0 -0
@@ -148,7 +148,8 @@ To add a new slash command: (1) add a `SlashCommand` entry to `COMMANDS`, (2) se
148
148
  2. `deepagents_code/model_config.py` — if the provider reads a *dedicated* endpoint env var, add `"provider_name": ("CANONICAL_BASE_URL", "ALTERNATE", ...)` to `PROVIDER_BASE_URL_ENV` (see guidelines below); omit the provider entirely when it has no provider-specific endpoint variable
149
149
  3. `pyproject.toml` — add `provider = ["langchain-provider>=X.Y.Z,<N.0.0"]` to `[project.optional-dependencies]` and include it in the `all-providers` composite extra
150
150
  4. `deepagents_code/model_config.py` — add `"provider_name"` to `RETRY_PARAM_BY_PROVIDER` if the provider's chat model accepts `max_retries`
151
- 5. `tests/unit_tests/test_model_config.py` — add `assert PROVIDER_API_KEY_ENV["provider_name"] == "ENV_VAR_NAME"` to `TestProviderApiKeyEnv.test_contains_major_providers`, and pin any `PROVIDER_BASE_URL_ENV` entry with a matching assertion
151
+ 5. `deepagents_code/widgets/auth.py` — add `"provider_name": "Display Name"` to `PROVIDER_DISPLAY_NAMES` so the `/auth` UI shows a branded label instead of the title-cased key, and (if the provider issues API keys from a self-serve page) `"provider_name": "https://…"` to `PROVIDER_API_KEY_URLS` so the prompt links straight to the key page
152
+ 6. `tests/unit_tests/test_model_config.py` — add `assert PROVIDER_API_KEY_ENV["provider_name"] == "ENV_VAR_NAME"` to `TestProviderApiKeyEnv.test_contains_major_providers`, and pin any `PROVIDER_BASE_URL_ENV` entry with a matching assertion
152
153
 
153
154
  ### `PROVIDER_BASE_URL_ENV` guidelines
154
155
 
@@ -2,6 +2,25 @@
2
2
 
3
3
  # Deep Agents Code Changelog
4
4
 
5
+ ## [0.1.19](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.18...deepagents-code==0.1.19) (2026-06-17)
6
+
7
+ ### Features
8
+
9
+ * Add latest frontier models to recommended list ([#4045](https://github.com/langchain-ai/deepagents/issues/4045)) ([1145356](https://github.com/langchain-ai/deepagents/commit/114535637eaee383c64eac5282bc9ac57007c83f))
10
+ * Dual-write agent traces to extra LangSmith projects ([#3998](https://github.com/langchain-ai/deepagents/issues/3998)) ([1b94cf3](https://github.com/langchain-ai/deepagents/commit/1b94cf322949e0cafd6f2bacf343fb0044ec5a8c))
11
+ * Prompt to install provider when selecting an uninstalled model ([#3981](https://github.com/langchain-ai/deepagents/issues/3981)) ([619207c](https://github.com/langchain-ai/deepagents/commit/619207c8d4d4308a9a3ab9d2d039506feeaf8a67))
12
+ * Note minimum OpenAI key permissions in `/auth` ([#4040](https://github.com/langchain-ai/deepagents/issues/4040)) ([14be63d](https://github.com/langchain-ai/deepagents/commit/14be63d476ed8dece75e20fff05016122c258be8))
13
+
14
+ ### Bug Fixes
15
+
16
+ * Exclude prompt prefix from `UserMessage` selection ([#4002](https://github.com/langchain-ai/deepagents/issues/4002)) ([8ee6ba6](https://github.com/langchain-ai/deepagents/commit/8ee6ba6e64895d3d36a5957627221ed7667bc1d4))
17
+
18
+ ## [0.1.18](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.17...deepagents-code==0.1.18) (2026-06-16)
19
+
20
+ ### Features
21
+
22
+ * Add provider-specific auth guidance ([#4004](https://github.com/langchain-ai/deepagents/issues/4004)) ([6a39247](https://github.com/langchain-ai/deepagents/commit/6a392471ba30089b1a63135494873d55209bb081))
23
+
5
24
  ## [0.1.17](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.16...deepagents-code==0.1.17) (2026-06-16)
6
25
 
7
26
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-code
3
- Version: 0.1.17
3
+ Version: 0.1.19
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/
@@ -122,7 +122,7 @@ Requires-Dist: langchain-openrouter<2.0.0,>=0.2.3; extra == 'openrouter'
122
122
  Provides-Extra: perplexity
123
123
  Requires-Dist: langchain-perplexity<2.0.0,>=1.4.0; extra == 'perplexity'
124
124
  Provides-Extra: quickjs
125
- Requires-Dist: langchain-quickjs<0.2.0,>=0.1.4; extra == 'quickjs'
125
+ Requires-Dist: langchain-quickjs<0.3.0,>=0.2.0; extra == 'quickjs'
126
126
  Provides-Extra: runloop
127
127
  Requires-Dist: langchain-runloop>=0.0.6; extra == 'runloop'
128
128
  Provides-Extra: together
@@ -122,6 +122,18 @@ KITTY_KEYBOARD = "DEEPAGENTS_CODE_KITTY_KEYBOARD"
122
122
  LANGSMITH_PROJECT = "DEEPAGENTS_CODE_LANGSMITH_PROJECT"
123
123
  """Override LangSmith project name for agent traces."""
124
124
 
125
+ LANGSMITH_REPLICA_PROJECTS = "DEEPAGENTS_CODE_LANGSMITH_REPLICA_PROJECTS"
126
+ """Comma-separated LangSmith project names to *also* write agent traces to.
127
+
128
+ When set (and tracing is active), each agent run is dual-written to the primary
129
+ deepagents-code project *and* one extra project via LangSmith write replicas.
130
+
131
+ Only the first listed project is used: the LangGraph server mirrors a run to a
132
+ single extra project, so any additional entries are dropped (with a warning).
133
+ The value is comma-separated for forward-compatibility, not because multiple
134
+ destinations are written today.
135
+ """
136
+
125
137
  NO_TERMINAL_ESCAPE = "DEEPAGENTS_CODE_NO_TERMINAL_ESCAPE"
126
138
  """Disable all terminal escape/control sequence output when enabled."""
127
139
 
@@ -165,6 +177,13 @@ SHELL_ALLOW_LIST = "DEEPAGENTS_CODE_SHELL_ALLOW_LIST"
165
177
  SHOW_HEADER = "DEEPAGENTS_CODE_SHOW_HEADER"
166
178
  """Show Textual's native header bar at the top of the TUI when enabled."""
167
179
 
180
+ SHOW_LANGSMITH_REPLICA_TRACING = "DEEPAGENTS_CODE_SHOW_LANGSMITH_REPLICA_TRACING"
181
+ """Show LangSmith replica project info in the startup splash when enabled.
182
+
183
+ Defaults to enabled; set to a falsy value (`0`, `false`, `no`, `off`, or empty)
184
+ to hide replica tracing details from the splash while leaving tracing active.
185
+ """
186
+
168
187
  THEME = "DEEPAGENTS_CODE_THEME"
169
188
  """Force the CLI to launch with this theme name when set."""
170
189
 
@@ -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.17" # x-release-please-version
5
+ __version__ = "0.1.19" # 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."""
@@ -202,6 +202,7 @@ if TYPE_CHECKING:
202
202
  from deepagents_code.textual_adapter import TextualUIAdapter
203
203
  from deepagents_code.widgets.approval import ApprovalMenu
204
204
  from deepagents_code.widgets.ask_user import AskUserMenu
205
+ from deepagents_code.widgets.model_selector import ModelSelectorScreen
205
206
  from deepagents_code.widgets.notification_center import (
206
207
  NotificationSuppressRequested,
207
208
  )
@@ -3984,7 +3985,30 @@ class DeepAgentsApp(App):
3984
3985
  return
3985
3986
 
3986
3987
  extra = names[0].lower()
3988
+ await self._install_extra(extra, force=force)
3987
3989
 
3990
+ async def _install_extra(
3991
+ self, extra: str, *, force: bool = False, auto_restart: bool = False
3992
+ ) -> bool:
3993
+ """Install a `deepagents-code` extra, mounting progress and restart offer.
3994
+
3995
+ Shared by the `/install <extra>` command and the model selector's
3996
+ install-on-select flow. Mounts its own status/error messages and offers
3997
+ a one-keypress restart for restart-capable extras.
3998
+
3999
+ Args:
4000
+ extra: The extra name to install (e.g. `"baseten"`, `"quickjs"`).
4001
+ force: Skip the "unknown extra" guard for valid-but-unlisted names.
4002
+ auto_restart: Restart the app-owned server immediately after a
4003
+ restart-capable install. Used only when the user selected a model
4004
+ that cannot load until the server respawns.
4005
+
4006
+ Returns:
4007
+ `True` when the extra installed successfully and, when `auto_restart`
4008
+ was requested, the server was restarted (or a fresh startup will
4009
+ load it); `False` otherwise. The interactive restart offer
4010
+ (non-`auto_restart` path) does not affect the return value.
4011
+ """
3988
4012
  try:
3989
4013
  from deepagents_code.config import _is_editable_install
3990
4014
  from deepagents_code.extras_info import (
@@ -4005,7 +4029,7 @@ class DeepAgentsApp(App):
4005
4029
  await self._mount_message(
4006
4030
  ErrorMessage(f"Install failed: {type(exc).__name__}: {exc}"),
4007
4031
  )
4008
- return
4032
+ return False
4009
4033
 
4010
4034
  if not is_valid_extra_name(extra):
4011
4035
  await self._mount_message(
@@ -4014,7 +4038,7 @@ class DeepAgentsApp(App):
4014
4038
  "alphanumeric with `-`, `_`, or `.` (PEP 508).",
4015
4039
  ),
4016
4040
  )
4017
- return
4041
+ return False
4018
4042
 
4019
4043
  if await asyncio.to_thread(_is_editable_install):
4020
4044
  await self._mount_message(
@@ -4023,7 +4047,7 @@ class DeepAgentsApp(App):
4023
4047
  + editable_extra_hint(extra),
4024
4048
  ),
4025
4049
  )
4026
- return
4050
+ return False
4027
4051
 
4028
4052
  # KNOWN_EXTRAS is a curated "did you mean" list, not the authoritative
4029
4053
  # set (that's pyproject, resolved by uv): defer to --force rather than
@@ -4036,7 +4060,7 @@ class DeepAgentsApp(App):
4036
4060
  await self._mount_message(
4037
4061
  ErrorMessage(f"Install failed: {type(exc).__name__}: {exc}"),
4038
4062
  )
4039
- return
4063
+ return False
4040
4064
  known = ", ".join(sorted(KNOWN_EXTRAS))
4041
4065
  await self._mount_message(
4042
4066
  AppMessage(
@@ -4047,7 +4071,7 @@ class DeepAgentsApp(App):
4047
4071
  f"`/install {extra} --force`",
4048
4072
  ),
4049
4073
  )
4050
- return
4074
+ return False
4051
4075
 
4052
4076
  log_path = create_update_log_path()
4053
4077
  # Load the restart modal before the upgrade rewrites our own package
@@ -4065,7 +4089,7 @@ class DeepAgentsApp(App):
4065
4089
  f"Install failed: {type(exc).__name__}: {exc}\nLog: {log_path}",
4066
4090
  ),
4067
4091
  )
4068
- return
4092
+ return False
4069
4093
  try:
4070
4094
  success, output = await perform_install_extra(extra, log_path=log_path)
4071
4095
  except (OSError, asyncio.CancelledError) as exc:
@@ -4077,7 +4101,7 @@ class DeepAgentsApp(App):
4077
4101
  f"Run manually: {manual_cmd}",
4078
4102
  ),
4079
4103
  )
4080
- return
4104
+ return False
4081
4105
 
4082
4106
  if not success:
4083
4107
  # Tail the last 200 chars — uv resolver prints the resolved
@@ -4090,7 +4114,7 @@ class DeepAgentsApp(App):
4090
4114
  f"Run manually: {manual_cmd}",
4091
4115
  ),
4092
4116
  )
4093
- return
4117
+ return False
4094
4118
 
4095
4119
  # Model-provider and sandbox extras are imported by the langgraph
4096
4120
  # server subprocess; `/restart` respawns that subprocess and picks
@@ -4099,16 +4123,60 @@ class DeepAgentsApp(App):
4099
4123
  # (`verify_interpreter_deps` gates `--interpreter`), so a full
4100
4124
  # relaunch is required.
4101
4125
  restart_capable = extra in MODEL_PROVIDER_EXTRAS or extra in SANDBOX_EXTRAS
4102
- if restart_capable:
4103
- next_step = "Run `/restart` to load it now, or relaunch dcode."
4104
- else:
4105
- next_step = "Exit and relaunch dcode to use the new dependencies."
4126
+ if restart_capable and auto_restart:
4127
+ if self._restart_after_install_is_unneeded():
4128
+ # No running server to respawn; a deferred/errored startup will
4129
+ # import the extra on its first spawn. Acknowledge the install
4130
+ # regardless of whether the config reload below succeeds.
4131
+ await self._mount_message(
4132
+ AppMessage(f"Installed extra '{extra}'."),
4133
+ )
4134
+ return await self._reload_configuration_for_restart()
4135
+ if await self._restart_after_install(extra):
4136
+ return True
4137
+ if self._server_kwargs is None:
4138
+ await self._mount_message(
4139
+ AppMessage(
4140
+ f"Installed extra '{extra}', but this app is connected "
4141
+ "to a remote LangGraph server. Relaunch dcode to load it, "
4142
+ "then select the model again."
4143
+ ),
4144
+ )
4145
+ else:
4146
+ await self._mount_message(
4147
+ AppMessage(
4148
+ f"Installed extra '{extra}', but couldn't restart the server "
4149
+ "automatically. Run `/restart` to load it, then select the "
4150
+ "model again."
4151
+ ),
4152
+ )
4153
+ return False
4106
4154
 
4107
- await self._mount_message(
4108
- AppMessage(f"Installed extra '{extra}'. {next_step}"),
4109
- )
4110
- if restart_capable:
4111
- await self._offer_restart_after_install(extra)
4155
+ if not restart_capable:
4156
+ if extra == "quickjs":
4157
+ # `quickjs` only does anything behind `--interpreter`, a
4158
+ # launch-only flag with a startup-time dependency gate, so a
4159
+ # `/restart` (which reuses the original launch settings) can't
4160
+ # enable it — a full relaunch with the flag is required.
4161
+ next_step = (
4162
+ "Exit and relaunch dcode with `--interpreter` to use it — "
4163
+ "see `dcode --help`."
4164
+ )
4165
+ else:
4166
+ next_step = "Exit and relaunch dcode to use the new dependencies."
4167
+ await self._mount_message(
4168
+ AppMessage(f"Installed extra '{extra}'. {next_step}"),
4169
+ )
4170
+ return True
4171
+
4172
+ # Restart-capable extra: announce success, then offer a one-keypress
4173
+ # restart. `_offer_restart_after_install` owns all follow-up messaging
4174
+ # (the prompt's button is the call to action when shown; it mounts a
4175
+ # `/restart`-or-relaunch hint itself when it can't show the prompt), so
4176
+ # a redundant "Run /restart" line is never appended here.
4177
+ await self._mount_message(AppMessage(f"Installed extra '{extra}'."))
4178
+ await self._offer_restart_after_install(extra)
4179
+ return True
4112
4180
 
4113
4181
  async def _handle_install_package(self, package: str, *, force: bool) -> None:
4114
4182
  """Install an arbitrary package into the dcode tool env via `uv --with`.
@@ -6447,8 +6515,11 @@ class DeepAgentsApp(App):
6447
6515
  with suppress(Exception):
6448
6516
  await queued_widget.remove()
6449
6517
  await self._mount_message(UserMessage(command))
6450
- link = Content.styled(url, TStyle(dim=True, italic=True, link=url))
6451
- await self._mount_message(AppMessage(link))
6518
+ msg = Content.assemble(
6519
+ f"Opening tracing project {project_name!r}:\n",
6520
+ (url, TStyle(dim=True, italic=True, link=url)),
6521
+ )
6522
+ await self._mount_message(AppMessage(msg))
6452
6523
 
6453
6524
  # Append directly — no dedup; each /trace invocation gets its own output.
6454
6525
  self._deferred_actions.append(
@@ -6457,8 +6528,11 @@ class DeepAgentsApp(App):
6457
6528
  return
6458
6529
 
6459
6530
  await self._mount_message(UserMessage(command))
6460
- link = Content.styled(url, TStyle(dim=True, italic=True, link=url))
6461
- await self._mount_message(AppMessage(link))
6531
+ msg = Content.assemble(
6532
+ f"Opening tracing project {project_name!r}:\n",
6533
+ (url, TStyle(dim=True, italic=True, link=url)),
6534
+ )
6535
+ await self._mount_message(AppMessage(msg))
6462
6536
 
6463
6537
  async def _handle_command(self, command: str) -> None:
6464
6538
  """Handle a slash command.
@@ -8785,7 +8859,7 @@ class DeepAgentsApp(App):
8785
8859
  *,
8786
8860
  curated: bool = False,
8787
8861
  result_callback: Callable[[tuple[str, str] | None], None] | None = None,
8788
- ) -> ModalScreen:
8862
+ ) -> ModelSelectorScreen:
8789
8863
  """Build the model selector screen with current app model state.
8790
8864
 
8791
8865
  Args:
@@ -8824,35 +8898,10 @@ class DeepAgentsApp(App):
8824
8898
  Args:
8825
8899
  extra_kwargs: Extra constructor kwargs from `--model-params`.
8826
8900
  """
8827
- from functools import partial
8828
8901
 
8829
8902
  def handle_result(result: tuple[str, str] | None) -> None:
8830
8903
  """Handle the model selector result."""
8831
- if result is not None:
8832
- model_spec, _ = result
8833
- if self._agent_running or self._shell_running or self._connecting:
8834
- self._defer_action(
8835
- DeferredAction(
8836
- kind="model_switch",
8837
- execute=partial(
8838
- self._switch_model,
8839
- model_spec,
8840
- extra_kwargs=extra_kwargs,
8841
- ),
8842
- ),
8843
- )
8844
- self.notify(
8845
- "Model will switch after current task completes.",
8846
- timeout=3,
8847
- )
8848
- else:
8849
- self.call_later(
8850
- partial(
8851
- self._switch_model,
8852
- model_spec,
8853
- extra_kwargs=extra_kwargs,
8854
- ),
8855
- )
8904
+ self._handle_model_selection(screen, result, extra_kwargs=extra_kwargs)
8856
8905
  # Refocus input after modal closes
8857
8906
  if self._chat_input:
8858
8907
  self._chat_input.focus_input()
@@ -8860,6 +8909,155 @@ class DeepAgentsApp(App):
8860
8909
  screen = self._build_model_selector_screen()
8861
8910
  self.push_screen(screen, handle_result)
8862
8911
 
8912
+ def _handle_model_selection(
8913
+ self,
8914
+ screen: ModelSelectorScreen,
8915
+ result: tuple[str, str] | None,
8916
+ *,
8917
+ extra_kwargs: dict[str, Any] | None = None,
8918
+ ) -> None:
8919
+ """Route a model-selector result to install-then-switch or a switch.
8920
+
8921
+ Args:
8922
+ screen: The dismissed selector, read for a confirmed install extra.
8923
+ result: The `(model_spec, provider)` pair, or `None` if cancelled.
8924
+ extra_kwargs: Extra constructor kwargs from `--model-params`.
8925
+ """
8926
+ if result is None:
8927
+ return
8928
+ model_spec, _ = result
8929
+ # When the selector confirmed installing a missing provider's extra,
8930
+ # install it first (with restart offer) before switching.
8931
+ extra = screen.pending_install_extra
8932
+ if extra:
8933
+ from functools import partial
8934
+
8935
+ self.call_later(
8936
+ partial(
8937
+ self._install_extra_then_switch,
8938
+ extra,
8939
+ model_spec,
8940
+ extra_kwargs=extra_kwargs,
8941
+ ),
8942
+ )
8943
+ else:
8944
+ self._dispatch_model_switch(model_spec, extra_kwargs=extra_kwargs)
8945
+
8946
+ def _dispatch_model_switch(
8947
+ self,
8948
+ model_spec: str,
8949
+ *,
8950
+ extra_kwargs: dict[str, Any] | None = None,
8951
+ ) -> None:
8952
+ """Switch to `model_spec` now, or defer until in-flight work finishes.
8953
+
8954
+ Args:
8955
+ model_spec: The `provider:model` spec to switch to.
8956
+ extra_kwargs: Extra constructor kwargs from `--model-params`.
8957
+ """
8958
+ from functools import partial
8959
+
8960
+ if self._agent_running or self._shell_running or self._connecting:
8961
+ self._defer_action(
8962
+ DeferredAction(
8963
+ kind="model_switch",
8964
+ execute=partial(
8965
+ self._switch_model,
8966
+ model_spec,
8967
+ extra_kwargs=extra_kwargs,
8968
+ ),
8969
+ ),
8970
+ )
8971
+ self.notify(
8972
+ "Model will switch after current task completes.",
8973
+ timeout=3,
8974
+ )
8975
+ else:
8976
+ self.call_later(
8977
+ partial(
8978
+ self._switch_model,
8979
+ model_spec,
8980
+ extra_kwargs=extra_kwargs,
8981
+ ),
8982
+ )
8983
+
8984
+ async def _install_extra_then_switch(
8985
+ self,
8986
+ extra: str,
8987
+ model_spec: str,
8988
+ *,
8989
+ extra_kwargs: dict[str, Any] | None = None,
8990
+ ) -> None:
8991
+ """Install a provider's extra, then switch to its model on success.
8992
+
8993
+ Args:
8994
+ extra: The extra that installs the model's provider integration.
8995
+ model_spec: The `provider:model` spec to switch to once installed.
8996
+ extra_kwargs: Extra constructor kwargs from `--model-params`.
8997
+ """
8998
+ # `_install_extra` already surfaced the reason on any failure.
8999
+ if not await self._install_extra(extra, auto_restart=True):
9000
+ return
9001
+ # The extra is now installed regardless of what happens next. If the
9002
+ # user dismisses the credential prompt, only the switch is cancelled —
9003
+ # the extra stays installed so they can switch later once a key is set.
9004
+ # The selector is already gone, so confirm the install landed rather
9005
+ # than leaving a silent no-op after a multi-step flow.
9006
+ if not await self._prompt_model_auth_if_needed(model_spec):
9007
+ await self._mount_message(
9008
+ AppMessage(
9009
+ f"Installed '{extra}'. Skipped switching to {model_spec} for "
9010
+ f"now — add credentials with `/auth`, then switch with "
9011
+ f"`/model` anytime.",
9012
+ ),
9013
+ )
9014
+ return
9015
+ self._dispatch_model_switch(model_spec, extra_kwargs=extra_kwargs)
9016
+
9017
+ async def _prompt_model_auth_if_needed(self, model_spec: str) -> bool:
9018
+ """Prompt for missing credentials before switching to `model_spec`.
9019
+
9020
+ Args:
9021
+ model_spec: The `provider:model` spec selected after installation.
9022
+
9023
+ Returns:
9024
+ `True` when switching can continue, or `False` when the user did not
9025
+ save required credentials.
9026
+ """
9027
+ # This assumes API-key-style providers: it always uses the generic
9028
+ # `AuthPromptScreen` (key / base-url), never the codex OAuth flow that
9029
+ # the selector routes separately. That holds because only providers
9030
+ # with a `_PROVIDER_DEPENDENCIES` extra reach the install-then-switch
9031
+ # path, and the OAuth providers (e.g. `openai_codex`) have no such
9032
+ # entry. If an OAuth provider ever gains an extra, route it to its
9033
+ # dedicated sign-in here rather than the key prompt.
9034
+ from deepagents_code.config import detect_provider
9035
+ from deepagents_code.model_config import (
9036
+ ModelSpec,
9037
+ get_credential_env_var,
9038
+ get_provider_auth_status,
9039
+ )
9040
+ from deepagents_code.widgets.auth import AuthPromptScreen, AuthResult
9041
+
9042
+ parsed = ModelSpec.try_parse(model_spec)
9043
+ provider = parsed.provider if parsed else detect_provider(model_spec)
9044
+ if not provider:
9045
+ return True
9046
+
9047
+ status = get_provider_auth_status(provider)
9048
+ if not status.blocks_start:
9049
+ return True
9050
+
9051
+ env_var = status.env_var or get_credential_env_var(provider)
9052
+ result = await self._push_screen_wait(
9053
+ AuthPromptScreen(
9054
+ provider,
9055
+ env_var,
9056
+ reason=f"Required to use {model_spec}",
9057
+ )
9058
+ )
9059
+ return result is AuthResult.SAVED
9060
+
8863
9061
  def _register_custom_themes(self) -> None:
8864
9062
  """Register all custom themes (built-in LC + user-defined) with Textual."""
8865
9063
  for name, entry in theme.get_registry().items():
@@ -10757,37 +10955,56 @@ class DeepAgentsApp(App):
10757
10955
  app-owned LangGraph server subprocess, so a `/restart` loads them
10758
10956
  without exiting the TUI. When dcode owns that subprocess and is idle,
10759
10957
  prompt to run the restart immediately instead of making the user type
10760
- `/restart`. Skipped while a run is in flight or the server is still
10761
- connecting/restarting (a restart cancels in-flight work and a
10762
- connecting server has nothing to respawn into yet) and in
10763
- remote-server mode (no subprocess to respawn) — every skipped path
10764
- already carries the manual-restart hint in the install message.
10958
+ `/restart`.
10959
+
10960
+ Owns all of its own follow-up messaging so the caller never appends a
10961
+ redundant hint:
10962
+
10963
+ - Owned + idle: show the prompt (its button is the call to action). If
10964
+ the prompt can't be shown, fall back to a `/restart` hint.
10965
+ - Owned + busy/connecting: a restart cancels in-flight work, so point
10966
+ at `/restart` for once the current task finishes.
10967
+ - No owned subprocess (remote server): `/restart` can't respawn it, so a
10968
+ full relaunch is the only way to load the package.
10765
10969
 
10766
10970
  Args:
10767
10971
  label: Installed extra/package name, surfaced in the prompt title.
10768
10972
  """
10769
10973
  if self._server_proc is None or self._server_kwargs is None:
10974
+ await self._mount_message(
10975
+ AppMessage(f"Relaunch dcode to load '{label}'."),
10976
+ )
10770
10977
  return
10771
10978
  if self._agent_running or self._connecting:
10979
+ await self._mount_message(
10980
+ AppMessage(
10981
+ f"Run `/restart` to load '{label}' once the current task finishes.",
10982
+ ),
10983
+ )
10772
10984
  return
10773
10985
 
10986
+ # Owned + idle. A `/restart` respawns the subprocess (same effect as a
10987
+ # relaunch, without exiting), so every couldn't-show-the-prompt path
10988
+ # below degrades to this hint rather than mentioning a relaunch.
10989
+ manual_hint = f"Run `/restart` to load '{label}' now."
10990
+
10774
10991
  try:
10775
10992
  from deepagents_code.widgets.restart_prompt import RestartPromptScreen
10776
10993
  except ModuleNotFoundError:
10777
10994
  # `/install` runs `uv tool install -U 'deepagents-code[...]'`, which
10778
10995
  # can rewrite deepagents-code's own on-disk package tree mid-session
10779
10996
  # (see `_ensure_restart_prompt_loaded`). A first import of the modal
10780
- # here may then fail with `ModuleNotFoundError`. The manual
10781
- # `/restart` hint was already mounted by the caller, so degrade to
10782
- # that instead of crashing the TUI. The catch is deliberately
10783
- # narrow a genuine `ImportError` from a broken modal still
10784
- # propagates rather than being mistaken for an upgrade race.
10997
+ # here may then fail with `ModuleNotFoundError`. Degrade to the
10998
+ # manual `/restart` hint instead of crashing the TUI. The catch is
10999
+ # deliberately narrow a genuine `ImportError` from a broken modal
11000
+ # still propagates rather than being mistaken for an upgrade race.
10785
11001
  logger.warning(
10786
- "restart_prompt unavailable after installing %r; leaving the "
10787
- "manual /restart hint in place",
11002
+ "restart_prompt unavailable after installing %r; falling back "
11003
+ "to the manual /restart hint",
10788
11004
  label,
10789
11005
  exc_info=True,
10790
11006
  )
11007
+ await self._mount_message(AppMessage(manual_hint))
10791
11008
  return
10792
11009
 
10793
11010
  choice: RestartChoice | None
@@ -10801,25 +11018,74 @@ class DeepAgentsApp(App):
10801
11018
  )
10802
11019
  except TimeoutError:
10803
11020
  logger.warning(
10804
- "Restart prompt after installing %r timed out; leaving the "
10805
- "manual /restart hint in place",
11021
+ "Restart prompt after installing %r timed out; falling back to "
11022
+ "the manual /restart hint",
10806
11023
  label,
10807
11024
  )
11025
+ await self._mount_message(AppMessage(manual_hint))
10808
11026
  return
10809
11027
  except Exception:
10810
11028
  # Modal could not be mounted (e.g. another modal hijacked the
10811
- # stack). Leave the manual `/restart` hint in place.
11029
+ # stack). Fall back to the manual `/restart` hint.
10812
11030
  logger.exception(
10813
11031
  "Failed to mount restart prompt after installing %r", label
10814
11032
  )
11033
+ await self._mount_message(AppMessage(manual_hint))
10815
11034
  return
10816
11035
 
10817
- if choice == "restart":
10818
- if not await self._reload_configuration_for_restart():
10819
- return
10820
- await self._mount_message(AppMessage("Restarting server..."))
10821
- if await self._restart_server_manual():
10822
- await self._mount_message(AppMessage("Restart complete."))
11036
+ # The pre-prompt guards above ran before the modal await; server state
11037
+ # can flip while the user reads the prompt (e.g. an agent run starts),
11038
+ # tripping `_restart_after_install`'s busy/no-server guards, which only
11039
+ # log. Surface a message so an explicit "restart" choice never looks
11040
+ # like a silent no-op. Mirrors the `auto_restart` path.
11041
+ if choice == "restart" and not await self._restart_after_install(label):
11042
+ await self._mount_message(
11043
+ AppMessage(
11044
+ f"Couldn't restart the server automatically to load "
11045
+ f"'{label}'. Run `/restart` to load it.",
11046
+ ),
11047
+ )
11048
+ # Otherwise the prompt was shown and the user made an informed choice;
11049
+ # no further hint is needed.
11050
+
11051
+ def _restart_after_install_is_unneeded(self) -> bool:
11052
+ """Return whether a fresh startup will load the installed dependency."""
11053
+ return (
11054
+ self._server_proc is None
11055
+ and self._server_kwargs is not None
11056
+ and (
11057
+ self._server_startup_deferred or self._server_startup_error is not None
11058
+ )
11059
+ )
11060
+
11061
+ async def _restart_after_install(self, label: str) -> bool:
11062
+ """Restart the app-owned server after installing a dependency.
11063
+
11064
+ Args:
11065
+ label: Installed extra/package name, used for logs and fallback copy.
11066
+
11067
+ Returns:
11068
+ `True` when the server restarted successfully; `False` when restart is
11069
+ not currently available or fails.
11070
+ """
11071
+ if self._server_proc is None or self._server_kwargs is None:
11072
+ logger.info(
11073
+ "Cannot auto-restart after installing %s: no app-owned server", label
11074
+ )
11075
+ return False
11076
+ if self._agent_running or self._connecting:
11077
+ logger.info(
11078
+ "Cannot auto-restart after installing %s: server is busy",
11079
+ label,
11080
+ )
11081
+ return False
11082
+ if not await self._reload_configuration_for_restart():
11083
+ return False
11084
+ await self._mount_message(AppMessage("Restarting server..."))
11085
+ if not await self._restart_server_manual():
11086
+ return False
11087
+ await self._mount_message(AppMessage("Restart complete."))
11088
+ return True
10823
11089
 
10824
11090
  async def _reload_configuration_for_restart(self) -> bool:
10825
11091
  """Reload config state before respawning the owned server.