shotgun-sh 0.2.5.dev1__tar.gz → 0.2.6__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.

Potentially problematic release.


This version of shotgun-sh might be problematic. Click here for more details.

Files changed (160) hide show
  1. shotgun_sh-0.2.6/PKG-INFO +125 -0
  2. shotgun_sh-0.2.6/README_PYPI.md +71 -0
  3. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/pyproject.toml +3 -2
  4. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/agent_manager.py +103 -44
  5. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/common.py +13 -45
  6. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/config/manager.py +4 -0
  7. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/export.py +4 -5
  8. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/anthropic.py +22 -2
  9. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/models.py +50 -2
  10. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/plan.py +4 -5
  11. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/research.py +4 -5
  12. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/specify.py +4 -5
  13. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tasks.py +4 -5
  14. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/__init__.py +0 -2
  15. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/build_constants.py +2 -2
  16. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/export.j2 +18 -1
  17. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +5 -1
  18. shotgun_sh-0.2.6/src/shotgun/prompts/agents/partials/interactive_mode.j2 +43 -0
  19. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/plan.j2 +1 -1
  20. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/research.j2 +1 -1
  21. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/tasks.j2 +1 -1
  22. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/telemetry.py +8 -0
  23. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat.py +185 -34
  24. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat_screen/history.py +59 -76
  25. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/welcome.py +10 -2
  26. shotgun_sh-0.2.5.dev1/PKG-INFO +0 -467
  27. shotgun_sh-0.2.5.dev1/src/shotgun/agents/tools/user_interaction.py +0 -37
  28. shotgun_sh-0.2.5.dev1/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -26
  29. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/.gitignore +0 -0
  30. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/LICENSE +0 -0
  31. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/README.md +0 -0
  32. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/hatch_build.py +0 -0
  33. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/__init__.py +0 -0
  34. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/__init__.py +0 -0
  35. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/config/__init__.py +0 -0
  36. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/config/constants.py +0 -0
  37. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/config/models.py +0 -0
  38. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/config/provider.py +0 -0
  39. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/conversation_history.py +0 -0
  40. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/conversation_manager.py +0 -0
  41. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/__init__.py +0 -0
  42. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/compaction.py +0 -0
  43. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/constants.py +0 -0
  44. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/context_extraction.py +0 -0
  45. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/history_building.py +0 -0
  46. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/history_processors.py +0 -0
  47. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/message_utils.py +0 -0
  48. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/__init__.py +0 -0
  49. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/base.py +0 -0
  50. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/openai.py +0 -0
  51. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/sentencepiece_counter.py +0 -0
  52. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/tokenizer_cache.py +0 -0
  53. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_counting/utils.py +0 -0
  54. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/history/token_estimation.py +0 -0
  55. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/llm.py +0 -0
  56. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/messages.py +0 -0
  57. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
  58. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
  59. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
  60. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
  61. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/models.py +0 -0
  62. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
  63. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
  64. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/file_management.py +0 -0
  65. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/web_search/__init__.py +0 -0
  66. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
  67. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
  68. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/web_search/openai.py +0 -0
  69. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/tools/web_search/utils.py +0 -0
  70. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/agents/usage_manager.py +0 -0
  71. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/api_endpoints.py +0 -0
  72. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/__init__.py +0 -0
  73. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/codebase/__init__.py +0 -0
  74. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/codebase/commands.py +0 -0
  75. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/codebase/models.py +0 -0
  76. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/config.py +0 -0
  77. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/export.py +0 -0
  78. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/feedback.py +0 -0
  79. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/models.py +0 -0
  80. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/plan.py +0 -0
  81. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/research.py +0 -0
  82. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/specify.py +0 -0
  83. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/tasks.py +0 -0
  84. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/update.py +0 -0
  85. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/cli/utils.py +0 -0
  86. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/__init__.py +0 -0
  87. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/__init__.py +0 -0
  88. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/change_detector.py +0 -0
  89. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/code_retrieval.py +0 -0
  90. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/cypher_models.py +0 -0
  91. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/ingestor.py +0 -0
  92. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/language_config.py +0 -0
  93. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/manager.py +0 -0
  94. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/nl_query.py +0 -0
  95. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/core/parser_loader.py +0 -0
  96. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/models.py +0 -0
  97. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/codebase/service.py +0 -0
  98. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/llm_proxy/__init__.py +0 -0
  99. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/llm_proxy/clients.py +0 -0
  100. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/llm_proxy/constants.py +0 -0
  101. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/logging_config.py +0 -0
  102. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/main.py +0 -0
  103. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/posthog_telemetry.py +0 -0
  104. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/__init__.py +0 -0
  105. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/__init__.py +0 -0
  106. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
  107. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
  108. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/specify.j2 +0 -0
  109. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
  110. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/agents/state/system_state.j2 +0 -0
  111. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/__init__.py +0 -0
  112. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
  113. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
  114. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
  115. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
  116. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
  117. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
  118. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/history/__init__.py +0 -0
  119. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
  120. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/history/summarization.j2 +0 -0
  121. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/loader.py +0 -0
  122. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/prompts/tools/web_search.j2 +0 -0
  123. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/py.typed +0 -0
  124. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sdk/__init__.py +0 -0
  125. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sdk/codebase.py +0 -0
  126. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sdk/exceptions.py +0 -0
  127. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sdk/models.py +0 -0
  128. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sdk/services.py +0 -0
  129. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/sentry_telemetry.py +0 -0
  130. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/shotgun_web/__init__.py +0 -0
  131. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/shotgun_web/client.py +0 -0
  132. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/shotgun_web/constants.py +0 -0
  133. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/shotgun_web/models.py +0 -0
  134. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/__init__.py +0 -0
  135. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/app.py +0 -0
  136. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/commands/__init__.py +0 -0
  137. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/components/prompt_input.py +0 -0
  138. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/components/spinner.py +0 -0
  139. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/components/splash.py +0 -0
  140. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/components/vertical_tail.py +0 -0
  141. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/filtered_codebase_service.py +0 -0
  142. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat.tcss +0 -0
  143. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
  144. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat_screen/command_providers.py +0 -0
  145. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/chat_screen/hint_message.py +0 -0
  146. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/directory_setup.py +0 -0
  147. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/feedback.py +0 -0
  148. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/model_picker.py +0 -0
  149. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/provider_config.py +0 -0
  150. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/shotgun_auth.py +0 -0
  151. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/screens/splash.py +0 -0
  152. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/styles.tcss +0 -0
  153. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/utils/__init__.py +0 -0
  154. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/tui/utils/mode_progress.py +0 -0
  155. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/__init__.py +0 -0
  156. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/datetime_utils.py +0 -0
  157. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/env_utils.py +0 -0
  158. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/file_system_utils.py +0 -0
  159. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/source_detection.py +0 -0
  160. {shotgun_sh-0.2.5.dev1 → shotgun_sh-0.2.6}/src/shotgun/utils/update_checker.py +0 -0
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: shotgun-sh
3
+ Version: 0.2.6
4
+ Summary: AI-powered research, planning, and task management CLI tool
5
+ Project-URL: Homepage, https://shotgun.sh/
6
+ Project-URL: Repository, https://github.com/shotgun-sh/shotgun
7
+ Project-URL: Issues, https://github.com/shotgun-sh/shotgun-alpha/issues
8
+ Project-URL: Discord, https://discord.gg/5RmY6J2N7s
9
+ Author-email: "Proofs.io" <hello@proofs.io>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,ai,cli,llm,planning,productivity,pydantic-ai,research,task-management
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: anthropic>=0.39.0
25
+ Requires-Dist: genai-prices>=0.0.27
26
+ Requires-Dist: httpx>=0.27.0
27
+ Requires-Dist: jinja2>=3.1.0
28
+ Requires-Dist: kuzu>=0.7.0
29
+ Requires-Dist: logfire[pydantic-ai]>=2.0.0
30
+ Requires-Dist: openai>=1.0.0
31
+ Requires-Dist: packaging>=23.0
32
+ Requires-Dist: posthog>=3.0.0
33
+ Requires-Dist: pydantic-ai>=0.0.14
34
+ Requires-Dist: rich>=13.0.0
35
+ Requires-Dist: sentencepiece>=0.2.0
36
+ Requires-Dist: sentry-sdk[pure-eval]>=2.0.0
37
+ Requires-Dist: textual-dev>=1.7.0
38
+ Requires-Dist: textual>=6.1.0
39
+ Requires-Dist: tiktoken>=0.7.0
40
+ Requires-Dist: tree-sitter-go>=0.23.0
41
+ Requires-Dist: tree-sitter-javascript>=0.23.0
42
+ Requires-Dist: tree-sitter-python>=0.23.0
43
+ Requires-Dist: tree-sitter-rust>=0.23.0
44
+ Requires-Dist: tree-sitter-typescript>=0.23.0
45
+ Requires-Dist: tree-sitter>=0.21.0
46
+ Requires-Dist: typer>=0.12.0
47
+ Requires-Dist: watchdog>=4.0.0
48
+ Provides-Extra: dev
49
+ Requires-Dist: commitizen>=3.13.0; extra == 'dev'
50
+ Requires-Dist: lefthook>=1.12.0; extra == 'dev'
51
+ Requires-Dist: mypy>=1.11.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # Shotgun
56
+
57
+ **Spec-Driven Development for AI Code Generation**
58
+
59
+ Shotgun is a CLI tool that turns work with AI code-gen tools from "I want to build X" into: **research → specs → plans → tasks → implementation**. It reads your entire codebase, coordinates AI agents to do the heavy lifting, and exports clean artifacts in the agents.md format so your code-gen tools actually know what they're building.
60
+
61
+ 🌐 **Learn more at [shotgun.sh](https://shotgun.sh/)**
62
+
63
+ ## Features
64
+
65
+ ### 📊 Complete Codebase Understanding
66
+
67
+ Before writing a single line, Shotgun reads all of it. Your patterns. Your dependencies. Your technical debt. Whether you're adding features, onboarding devs, planning migrations, or refactoring - Shotgun knows what you're working with.
68
+
69
+ ### 🔄 Five Modes. One Journey. Zero Gaps.
70
+
71
+ **Research** (what exists) → **Specify** (what to build) → **Plan** (how to build) → **Tasks** (break it down) → **Export** (to any tool)
72
+
73
+ Not another chatbot. A complete workflow where each mode feeds the next.
74
+
75
+ ### ➡️ Export to agents.md
76
+
77
+ Outputs plug into many code-generation tools including Codex, Cursor, Warp, Devin, opencode, Jules, and more.
78
+
79
+ ### 📝 Specs That Don't Die in Slack
80
+
81
+ Every research finding, every architectural decision, every "here's why we didn't use that library" - captured as markdown in your repo. Version controlled. Searchable.
82
+
83
+ ## Installation
84
+
85
+ ### Using pipx (Recommended)
86
+
87
+ ```bash
88
+ pipx install shotgun-sh
89
+ ```
90
+
91
+ **Why pipx?** It installs Shotgun in an isolated environment, preventing dependency conflicts with your other Python projects.
92
+
93
+ ### Using pip
94
+
95
+ ```bash
96
+ pip install shotgun-sh
97
+ ```
98
+
99
+ ## Quick Start
100
+
101
+ ```bash
102
+ # Research your codebase or a topic
103
+ shotgun research "What is our authentication flow?"
104
+
105
+ # Generate specifications
106
+ shotgun spec "Add OAuth2 authentication"
107
+
108
+ # Create an implementation plan
109
+ shotgun plan "Build user dashboard"
110
+
111
+ # Break down into tasks
112
+ shotgun tasks "Implement payment system"
113
+
114
+ # Export to agents.md format for your code-gen tools
115
+ shotgun export
116
+ ```
117
+
118
+ ## Support
119
+
120
+ Have questions? Join our community on **[Discord](https://discord.gg/5RmY6J2N7s)**
121
+
122
+ ---
123
+
124
+ **License:** MIT
125
+ **Python:** 3.11+
@@ -0,0 +1,71 @@
1
+ # Shotgun
2
+
3
+ **Spec-Driven Development for AI Code Generation**
4
+
5
+ Shotgun is a CLI tool that turns work with AI code-gen tools from "I want to build X" into: **research → specs → plans → tasks → implementation**. It reads your entire codebase, coordinates AI agents to do the heavy lifting, and exports clean artifacts in the agents.md format so your code-gen tools actually know what they're building.
6
+
7
+ 🌐 **Learn more at [shotgun.sh](https://shotgun.sh/)**
8
+
9
+ ## Features
10
+
11
+ ### 📊 Complete Codebase Understanding
12
+
13
+ Before writing a single line, Shotgun reads all of it. Your patterns. Your dependencies. Your technical debt. Whether you're adding features, onboarding devs, planning migrations, or refactoring - Shotgun knows what you're working with.
14
+
15
+ ### 🔄 Five Modes. One Journey. Zero Gaps.
16
+
17
+ **Research** (what exists) → **Specify** (what to build) → **Plan** (how to build) → **Tasks** (break it down) → **Export** (to any tool)
18
+
19
+ Not another chatbot. A complete workflow where each mode feeds the next.
20
+
21
+ ### ➡️ Export to agents.md
22
+
23
+ Outputs plug into many code-generation tools including Codex, Cursor, Warp, Devin, opencode, Jules, and more.
24
+
25
+ ### 📝 Specs That Don't Die in Slack
26
+
27
+ Every research finding, every architectural decision, every "here's why we didn't use that library" - captured as markdown in your repo. Version controlled. Searchable.
28
+
29
+ ## Installation
30
+
31
+ ### Using pipx (Recommended)
32
+
33
+ ```bash
34
+ pipx install shotgun-sh
35
+ ```
36
+
37
+ **Why pipx?** It installs Shotgun in an isolated environment, preventing dependency conflicts with your other Python projects.
38
+
39
+ ### Using pip
40
+
41
+ ```bash
42
+ pip install shotgun-sh
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```bash
48
+ # Research your codebase or a topic
49
+ shotgun research "What is our authentication flow?"
50
+
51
+ # Generate specifications
52
+ shotgun spec "Add OAuth2 authentication"
53
+
54
+ # Create an implementation plan
55
+ shotgun plan "Build user dashboard"
56
+
57
+ # Break down into tasks
58
+ shotgun tasks "Implement payment system"
59
+
60
+ # Export to agents.md format for your code-gen tools
61
+ shotgun export
62
+ ```
63
+
64
+ ## Support
65
+
66
+ Have questions? Join our community on **[Discord](https://discord.gg/5RmY6J2N7s)**
67
+
68
+ ---
69
+
70
+ **License:** MIT
71
+ **Python:** 3.11+
@@ -1,8 +1,8 @@
1
1
  [project]
2
2
  name = "shotgun-sh"
3
- version = "0.2.5.dev1"
3
+ version = "0.2.6"
4
4
  description = "AI-powered research, planning, and task management CLI tool"
5
- readme = "README.md"
5
+ readme = "README_PYPI.md"
6
6
  license = { text = "MIT" }
7
7
  authors = [
8
8
  { name = "Proofs.io", email = "hello@proofs.io" }
@@ -76,6 +76,7 @@ packages = ["src/shotgun"]
76
76
  include = [
77
77
  "/src",
78
78
  "/README.md",
79
+ "/README_PYPI.md",
79
80
  "/LICENSE",
80
81
  "/pyproject.toml"
81
82
  ]
@@ -10,8 +10,6 @@ if TYPE_CHECKING:
10
10
 
11
11
  from pydantic_ai import (
12
12
  Agent,
13
- DeferredToolRequests,
14
- DeferredToolResults,
15
13
  RunContext,
16
14
  UsageLimits,
17
15
  )
@@ -36,7 +34,8 @@ from textual.message import Message
36
34
  from textual.widget import Widget
37
35
 
38
36
  from shotgun.agents.common import add_system_prompt_message, add_system_status_message
39
- from shotgun.agents.models import AgentType, FileOperation
37
+ from shotgun.agents.config.models import KeyProvider
38
+ from shotgun.agents.models import AgentResponse, AgentType, FileOperation
40
39
  from shotgun.posthog_telemetry import track_event
41
40
  from shotgun.tui.screens.chat_screen.hint_message import HintMessage
42
41
  from shotgun.utils.source_detection import detect_source
@@ -44,7 +43,7 @@ from shotgun.utils.source_detection import detect_source
44
43
  from .export import create_export_agent
45
44
  from .history.compaction import apply_persistent_compaction
46
45
  from .messages import AgentSystemPrompt
47
- from .models import AgentDeps, AgentRuntimeOptions, UserAnswer
46
+ from .models import AgentDeps, AgentRuntimeOptions
48
47
  from .plan import create_plan_agent
49
48
  from .research import create_research_agent
50
49
  from .specify import create_specify_agent
@@ -91,6 +90,25 @@ class PartialResponseMessage(Message):
91
90
  self.is_last = is_last
92
91
 
93
92
 
93
+ class ClarifyingQuestionsMessage(Message):
94
+ """Event posted when agent returns clarifying questions."""
95
+
96
+ def __init__(
97
+ self,
98
+ questions: list[str],
99
+ response_text: str,
100
+ ) -> None:
101
+ """Initialize the clarifying questions message.
102
+
103
+ Args:
104
+ questions: List of clarifying questions from the agent
105
+ response_text: The agent's response text before asking questions
106
+ """
107
+ super().__init__()
108
+ self.questions = questions
109
+ self.response_text = response_text
110
+
111
+
94
112
  @dataclass(slots=True)
95
113
  class _PartialStreamState:
96
114
  """Tracks streamed messages while handling a single agent run."""
@@ -157,8 +175,12 @@ class AgentManager(Widget):
157
175
  self.recently_change_files: list[FileOperation] = []
158
176
  self._stream_state: _PartialStreamState | None = None
159
177
 
178
+ # Q&A mode state for structured output questions
179
+ self._qa_questions: list[str] | None = None
180
+ self._qa_mode_active: bool = False
181
+
160
182
  @property
161
- def current_agent(self) -> Agent[AgentDeps, str | DeferredToolRequests]:
183
+ def current_agent(self) -> Agent[AgentDeps, AgentResponse]:
162
184
  """Get the currently active agent.
163
185
 
164
186
  Returns:
@@ -166,9 +188,7 @@ class AgentManager(Widget):
166
188
  """
167
189
  return self._get_agent(self._current_agent_type)
168
190
 
169
- def _get_agent(
170
- self, agent_type: AgentType
171
- ) -> Agent[AgentDeps, str | DeferredToolRequests]:
191
+ def _get_agent(self, agent_type: AgentType) -> Agent[AgentDeps, AgentResponse]:
172
192
  """Get agent by type.
173
193
 
174
194
  Args:
@@ -251,9 +271,8 @@ class AgentManager(Widget):
251
271
  *,
252
272
  deps: AgentDeps | None = None,
253
273
  usage_limits: UsageLimits | None = None,
254
- deferred_tool_results: DeferredToolResults | None = None,
255
274
  **kwargs: Any,
256
- ) -> AgentRunResult[str | DeferredToolRequests]:
275
+ ) -> AgentRunResult[AgentResponse]:
257
276
  """Run the current agent with automatic message history management.
258
277
 
259
278
  This method wraps the agent's run method, automatically injecting the
@@ -263,7 +282,6 @@ class AgentManager(Widget):
263
282
  prompt: Optional prompt to send to the agent.
264
283
  deps: Optional dependencies override (defaults to manager's deps).
265
284
  usage_limits: Optional usage limits for the agent run.
266
- deferred_tool_results: Optional deferred tool results for continuing a conversation.
267
285
  **kwargs: Additional keyword arguments to pass to the agent.
268
286
 
269
287
  Returns:
@@ -273,15 +291,6 @@ class AgentManager(Widget):
273
291
  # Use merged deps (shared state + agent-specific system prompt) if not provided
274
292
  if deps is None:
275
293
  deps = self._create_merged_deps(self._current_agent_type)
276
- ask_user_part = self.get_unanswered_ask_user_part()
277
- if ask_user_part and prompt:
278
- if not deferred_tool_results:
279
- deferred_tool_results = DeferredToolResults()
280
- deferred_tool_results.calls[ask_user_part.tool_call_id] = UserAnswer(
281
- answer=prompt,
282
- tool_call_id=ask_user_part.tool_call_id,
283
- )
284
- prompt = None
285
294
 
286
295
  # Ensure deps is not None
287
296
  if deps is None:
@@ -359,40 +368,104 @@ class AgentManager(Widget):
359
368
  model_name = ""
360
369
  if hasattr(deps, "llm_model") and deps.llm_model is not None:
361
370
  model_name = deps.llm_model.name
362
- is_gpt5 = ( # streaming is likely not supported for gpt5. It varies between keys.
363
- "gpt-5" in model_name.lower()
371
+
372
+ # Check if it's a Shotgun account
373
+ is_shotgun_account = (
374
+ hasattr(deps, "llm_model")
375
+ and deps.llm_model is not None
376
+ and deps.llm_model.key_provider == KeyProvider.SHOTGUN
364
377
  )
365
378
 
379
+ # Only disable streaming for GPT-5 if NOT a Shotgun account
380
+ # Shotgun accounts support streaming for GPT-5
381
+ is_gpt5_byok = "gpt-5" in model_name.lower() and not is_shotgun_account
382
+
366
383
  # Track message send event
367
384
  event_name = f"message_send_{self._current_agent_type.value}"
368
385
  track_event(
369
386
  event_name,
370
387
  {
371
388
  "has_prompt": prompt is not None,
372
- "has_deferred_results": deferred_tool_results is not None,
373
389
  "model_name": model_name,
374
390
  },
375
391
  )
376
392
 
377
393
  try:
378
- result: AgentRunResult[
379
- str | DeferredToolRequests
380
- ] = await self.current_agent.run(
394
+ result: AgentRunResult[AgentResponse] = await self.current_agent.run(
381
395
  prompt,
382
396
  deps=deps,
383
397
  usage_limits=usage_limits,
384
398
  message_history=message_history,
385
- deferred_tool_results=deferred_tool_results,
386
- event_stream_handler=self._handle_event_stream if not is_gpt5 else None,
399
+ event_stream_handler=self._handle_event_stream
400
+ if not is_gpt5_byok
401
+ else None,
387
402
  **kwargs,
388
403
  )
389
404
  finally:
390
405
  self._stream_state = None
391
406
 
407
+ # Agent ALWAYS returns AgentResponse with structured output
408
+ agent_response = result.output
409
+ logger.debug("Agent returned structured AgentResponse")
410
+
411
+ # Always add the agent's response messages to maintain conversation history
392
412
  self.ui_message_history = original_messages + cast(
393
413
  list[ModelRequest | ModelResponse | HintMessage], result.new_messages()
394
414
  )
395
415
 
416
+ # Check if there are clarifying questions
417
+ if agent_response.clarifying_questions:
418
+ logger.info(
419
+ f"Agent has {len(agent_response.clarifying_questions)} clarifying questions"
420
+ )
421
+
422
+ # Add agent's response first if present
423
+ if agent_response.response:
424
+ self.ui_message_history.append(
425
+ HintMessage(message=agent_response.response)
426
+ )
427
+
428
+ if len(agent_response.clarifying_questions) == 1:
429
+ # Single question - treat as non-blocking suggestion, DON'T enter Q&A mode
430
+ self.ui_message_history.append(
431
+ HintMessage(message=f"💡 {agent_response.clarifying_questions[0]}")
432
+ )
433
+ else:
434
+ # Multiple questions (2+) - enter Q&A mode
435
+ self._qa_questions = agent_response.clarifying_questions
436
+ self._qa_mode_active = True
437
+
438
+ # Show intro with list, then first question
439
+ questions_list_with_intro = (
440
+ f"I have {len(agent_response.clarifying_questions)} questions:\n\n"
441
+ + "\n".join(
442
+ f"{i + 1}. {q}"
443
+ for i, q in enumerate(agent_response.clarifying_questions)
444
+ )
445
+ )
446
+ self.ui_message_history.append(
447
+ HintMessage(message=questions_list_with_intro)
448
+ )
449
+ self.ui_message_history.append(
450
+ HintMessage(
451
+ message=f"**Q1:** {agent_response.clarifying_questions[0]}"
452
+ )
453
+ )
454
+
455
+ # Post event to TUI to update Q&A mode state (only for multiple questions)
456
+ self.post_message(
457
+ ClarifyingQuestionsMessage(
458
+ questions=agent_response.clarifying_questions,
459
+ response_text=agent_response.response,
460
+ )
461
+ )
462
+ else:
463
+ # No clarifying questions - just show the response if present
464
+ if agent_response.response and agent_response.response.strip():
465
+ self.ui_message_history.append(
466
+ HintMessage(message=agent_response.response)
467
+ )
468
+
396
469
  # Apply compaction to persistent message history to prevent cascading growth
397
470
  all_messages = result.all_messages()
398
471
  self.message_history = await apply_persistent_compaction(all_messages, deps)
@@ -405,6 +478,7 @@ class AgentManager(Widget):
405
478
  file_operations = deps.file_tracker.operations.copy()
406
479
  self.recently_change_files = file_operations
407
480
 
481
+ # Post message history update (hints are now added synchronously above)
408
482
  self._post_messages_updated(file_operations)
409
483
 
410
484
  return result
@@ -691,22 +765,6 @@ class AgentManager(Widget):
691
765
  self.ui_message_history.append(message)
692
766
  self._post_messages_updated()
693
767
 
694
- def get_unanswered_ask_user_part(self) -> ToolCallPart | None:
695
- if not self.message_history:
696
- return None
697
- self.last_response = self.message_history[-1]
698
- ## we're searching for unanswered ask_user parts
699
- found_tool = next(
700
- (
701
- part
702
- for part in self.message_history[-1].parts
703
- if isinstance(part, ToolCallPart) and part.tool_name == "ask_user"
704
- ),
705
- None,
706
- )
707
-
708
- return found_tool
709
-
710
768
 
711
769
  # Re-export AgentType for backward compatibility
712
770
  __all__ = [
@@ -714,4 +772,5 @@ __all__ = [
714
772
  "AgentType",
715
773
  "MessageHistoryUpdated",
716
774
  "PartialResponseMessage",
775
+ "ClarifyingQuestionsMessage",
717
776
  ]
@@ -1,14 +1,11 @@
1
1
  """Common utilities for agent creation and management."""
2
2
 
3
- import asyncio
4
3
  from collections.abc import Callable
5
4
  from pathlib import Path
6
5
  from typing import Any
7
6
 
8
7
  from pydantic_ai import (
9
8
  Agent,
10
- DeferredToolRequests,
11
- DeferredToolResults,
12
9
  RunContext,
13
10
  UsageLimits,
14
11
  )
@@ -19,7 +16,7 @@ from pydantic_ai.messages import (
19
16
  )
20
17
 
21
18
  from shotgun.agents.config import ProviderType, get_provider_model
22
- from shotgun.agents.models import AgentType
19
+ from shotgun.agents.models import AgentResponse, AgentType
23
20
  from shotgun.logging_config import get_logger
24
21
  from shotgun.prompts import PromptLoader
25
22
  from shotgun.sdk.services import get_codebase_service
@@ -28,12 +25,10 @@ from shotgun.utils.datetime_utils import get_datetime_context
28
25
  from shotgun.utils.file_system_utils import get_shotgun_base_path
29
26
 
30
27
  from .history import token_limit_compactor
31
- from .history.compaction import apply_persistent_compaction
32
28
  from .messages import AgentSystemPrompt, SystemStatusPrompt
33
29
  from .models import AgentDeps, AgentRuntimeOptions, PipelineConfigEntry
34
30
  from .tools import (
35
31
  append_file,
36
- ask_user,
37
32
  codebase_shell,
38
33
  directory_lister,
39
34
  file_read,
@@ -106,7 +101,7 @@ def create_base_agent(
106
101
  additional_tools: list[Any] | None = None,
107
102
  provider: ProviderType | None = None,
108
103
  agent_mode: AgentType | None = None,
109
- ) -> tuple[Agent[AgentDeps, str | DeferredToolRequests], AgentDeps]:
104
+ ) -> tuple[Agent[AgentDeps, AgentResponse], AgentDeps]:
110
105
  """Create a base agent with common configuration.
111
106
 
112
107
  Args:
@@ -164,7 +159,7 @@ def create_base_agent(
164
159
 
165
160
  agent = Agent(
166
161
  model,
167
- output_type=[str, DeferredToolRequests],
162
+ output_type=AgentResponse,
168
163
  deps_type=AgentDeps,
169
164
  instrument=True,
170
165
  history_processors=[history_processor],
@@ -179,11 +174,6 @@ def create_base_agent(
179
174
  for tool in additional_tools or []:
180
175
  agent.tool_plain(tool)
181
176
 
182
- # Register interactive tool conditionally based on deps
183
- if deps.interactive_mode:
184
- agent.tool(ask_user)
185
- logger.debug("📞 Interactive mode enabled - ask_user tool registered")
186
-
187
177
  # Register common file management tools (always available)
188
178
  agent.tool(write_file)
189
179
  agent.tool(append_file)
@@ -323,7 +313,9 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
323
313
  if prior_toc:
324
314
  # Add section with XML tags
325
315
  toc_sections.append(
326
- f'<TABLE_OF_CONTENTS file_name="{prior_file}">\n{prior_toc}\n</TABLE_OF_CONTENTS>'
316
+ f'<TABLE_OF_CONTENTS file_name="{prior_file}">\n'
317
+ f"{prior_toc}\n"
318
+ f"</TABLE_OF_CONTENTS>"
327
319
  )
328
320
 
329
321
  # Extract TOC from own file (full detail)
@@ -334,7 +326,9 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
334
326
  # Put own file TOC at the beginning with XML tags
335
327
  toc_sections.insert(
336
328
  0,
337
- f'<TABLE_OF_CONTENTS file_name="{config.own_file}">\n{own_toc}\n</TABLE_OF_CONTENTS>',
329
+ f'<TABLE_OF_CONTENTS file_name="{config.own_file}">\n'
330
+ f"{own_toc}\n"
331
+ f"</TABLE_OF_CONTENTS>",
338
332
  )
339
333
 
340
334
  # Combine all sections
@@ -476,7 +470,8 @@ async def add_system_prompt_message(
476
470
  message_history = message_history or []
477
471
 
478
472
  # Create a minimal RunContext to call the system prompt function
479
- # We'll pass None for model and usage since they're not used by our system prompt functions
473
+ # We'll pass None for model and usage since they're not used
474
+ # by our system prompt functions
480
475
  context = type(
481
476
  "RunContext", (), {"deps": deps, "retry": 0, "model": None, "usage": None}
482
477
  )()
@@ -500,12 +495,12 @@ async def add_system_prompt_message(
500
495
 
501
496
 
502
497
  async def run_agent(
503
- agent: Agent[AgentDeps, str | DeferredToolRequests],
498
+ agent: Agent[AgentDeps, AgentResponse],
504
499
  prompt: str,
505
500
  deps: AgentDeps,
506
501
  message_history: list[ModelMessage] | None = None,
507
502
  usage_limits: UsageLimits | None = None,
508
- ) -> AgentRunResult[str | DeferredToolRequests]:
503
+ ) -> AgentRunResult[AgentResponse]:
509
504
  # Clear file tracker for new run
510
505
  deps.file_tracker.clear()
511
506
  logger.debug("🔧 Cleared file tracker for new agent run")
@@ -520,33 +515,6 @@ async def run_agent(
520
515
  message_history=message_history,
521
516
  )
522
517
 
523
- # Apply persistent compaction to prevent cascading token growth across CLI commands
524
- messages = await apply_persistent_compaction(result.all_messages(), deps)
525
- while isinstance(result.output, DeferredToolRequests):
526
- logger.info("got deferred tool requests")
527
- await deps.queue.join()
528
- requests = result.output
529
- done, _ = await asyncio.wait(deps.tasks)
530
-
531
- task_results = [task.result() for task in done]
532
- task_results_by_tool_call_id = {
533
- result.tool_call_id: result.answer for result in task_results
534
- }
535
- logger.info("got task results", task_results_by_tool_call_id)
536
- results = DeferredToolResults()
537
- for call in requests.calls:
538
- results.calls[call.tool_call_id] = task_results_by_tool_call_id[
539
- call.tool_call_id
540
- ]
541
- result = await agent.run(
542
- deps=deps,
543
- usage_limits=usage_limits,
544
- message_history=messages,
545
- deferred_tool_results=results,
546
- )
547
- # Apply persistent compaction to prevent cascading token growth in multi-turn loops
548
- messages = await apply_persistent_compaction(result.all_messages(), deps)
549
-
550
518
  # Log file operations summary if any files were modified
551
519
  if deps.file_tracker.operations:
552
520
  summary = deps.file_tracker.format_summary()
@@ -249,6 +249,10 @@ class ConfigManager:
249
249
  if provider_enum in provider_models:
250
250
  config.selected_model = provider_models[provider_enum]
251
251
 
252
+ # Mark welcome screen as shown when BYOK provider is configured
253
+ # This prevents the welcome screen from showing again after user has made their choice
254
+ config.shown_welcome_screen = True
255
+
252
256
  self.save(config)
253
257
 
254
258
  def clear_provider_key(self, provider: ProviderType | str) -> None:
@@ -4,7 +4,6 @@ from functools import partial
4
4
 
5
5
  from pydantic_ai import (
6
6
  Agent,
7
- DeferredToolRequests,
8
7
  )
9
8
  from pydantic_ai.agent import AgentRunResult
10
9
  from pydantic_ai.messages import ModelMessage
@@ -19,14 +18,14 @@ from .common import (
19
18
  create_usage_limits,
20
19
  run_agent,
21
20
  )
22
- from .models import AgentDeps, AgentRuntimeOptions, AgentType
21
+ from .models import AgentDeps, AgentResponse, AgentRuntimeOptions, AgentType
23
22
 
24
23
  logger = get_logger(__name__)
25
24
 
26
25
 
27
26
  def create_export_agent(
28
27
  agent_runtime_options: AgentRuntimeOptions, provider: ProviderType | None = None
29
- ) -> tuple[Agent[AgentDeps, str | DeferredToolRequests], AgentDeps]:
28
+ ) -> tuple[Agent[AgentDeps, AgentResponse], AgentDeps]:
30
29
  """Create an export agent with file management capabilities.
31
30
 
32
31
  Args:
@@ -50,11 +49,11 @@ def create_export_agent(
50
49
 
51
50
 
52
51
  async def run_export_agent(
53
- agent: Agent[AgentDeps, str | DeferredToolRequests],
52
+ agent: Agent[AgentDeps, AgentResponse],
54
53
  instruction: str,
55
54
  deps: AgentDeps,
56
55
  message_history: list[ModelMessage] | None = None,
57
- ) -> AgentRunResult[str | DeferredToolRequests]:
56
+ ) -> AgentRunResult[AgentResponse]:
58
57
  """Export artifacts based on the given instruction.
59
58
 
60
59
  Args: