shotgun-sh 0.7.3.dev1__tar.gz → 0.7.3.dev2__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 (297) hide show
  1. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/PKG-INFO +1 -1
  2. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/pyproject.toml +1 -1
  3. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/manager.py +10 -1
  4. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/models.py +17 -3
  5. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/provider.py +103 -4
  6. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/analyzer.py +1 -1
  7. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/compaction.py +2 -2
  8. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/history_processors.py +3 -3
  9. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/utils.py +4 -0
  10. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/__init__.py +17 -4
  11. shotgun_sh-0.7.3.dev2/src/shotgun/agents/tools/web_search/openai_compatible.py +136 -0
  12. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/context.py +1 -1
  13. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/run.py +14 -0
  14. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/main.py +15 -0
  15. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/settings.py +34 -0
  16. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/app.py +18 -2
  17. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/context_indicator.py +24 -14
  18. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/command_providers.py +48 -20
  19. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/widget_coordinator.py +3 -5
  20. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/.gitignore +0 -0
  21. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/LICENSE +0 -0
  22. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/README.md +0 -0
  23. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/hatch_build.py +0 -0
  24. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/__init__.py +0 -0
  25. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/__init__.py +0 -0
  26. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/agent_manager.py +0 -0
  27. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/cancellation.py +0 -0
  28. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/common.py +0 -0
  29. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/README.md +0 -0
  30. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/__init__.py +0 -0
  31. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/constants.py +0 -0
  32. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/streaming_test.py +0 -0
  33. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/__init__.py +0 -0
  34. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/constants.py +0 -0
  35. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/formatter.py +0 -0
  36. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/models.py +0 -0
  37. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/__init__.py +0 -0
  38. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/filters.py +0 -0
  39. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/__init__.py +0 -0
  40. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/chunking.py +0 -0
  41. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/constants.py +0 -0
  42. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/context_extraction.py +0 -0
  43. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/file_content_deduplication.py +0 -0
  44. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/history_building.py +0 -0
  45. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/message_utils.py +0 -0
  46. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/__init__.py +0 -0
  47. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/anthropic.py +0 -0
  48. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/base.py +0 -0
  49. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/openai.py +0 -0
  50. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/sentencepiece_counter.py +0 -0
  51. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/tokenizer_cache.py +0 -0
  52. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_estimation.py +0 -0
  53. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/manager.py +0 -0
  54. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/models.py +0 -0
  55. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/error/__init__.py +0 -0
  56. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/error/models.py +0 -0
  57. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/export.py +0 -0
  58. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/file_read.py +0 -0
  59. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/gemini3_patch.py +0 -0
  60. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/llm.py +0 -0
  61. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/messages.py +0 -0
  62. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/models.py +0 -0
  63. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/plan.py +0 -0
  64. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/research.py +0 -0
  65. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/__init__.py +0 -0
  66. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/models.py +0 -0
  67. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/router.py +0 -0
  68. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/__init__.py +0 -0
  69. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/delegation_tools.py +0 -0
  70. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/plan_tools.py +0 -0
  71. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/runner.py +0 -0
  72. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/specify.py +0 -0
  73. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tasks.py +0 -0
  74. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/__init__.py +0 -0
  75. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
  76. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
  77. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
  78. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
  79. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/models.py +0 -0
  80. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
  81. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
  82. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/file_management.py +0 -0
  83. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/file_read_tools/__init__.py +0 -0
  84. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/file_read_tools/multimodal_file_read.py +0 -0
  85. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/__init__.py +0 -0
  86. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/insert_section.py +0 -0
  87. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/models.py +0 -0
  88. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/remove_section.py +0 -0
  89. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/replace_section.py +0 -0
  90. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/utils.py +0 -0
  91. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/mermaid_validation.py +0 -0
  92. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/registry.py +0 -0
  93. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
  94. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
  95. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/openai.py +0 -0
  96. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/utils.py +0 -0
  97. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/usage_manager.py +0 -0
  98. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/api_endpoints.py +0 -0
  99. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/__init__.py +0 -0
  100. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/errors.py +0 -0
  101. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/models.py +0 -0
  102. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/parser.py +0 -0
  103. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/processor.py +0 -0
  104. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/build_constants.py +0 -0
  105. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/__init__.py +0 -0
  106. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/clear.py +0 -0
  107. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/__init__.py +0 -0
  108. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/commands.py +0 -0
  109. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/models.py +0 -0
  110. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/compact.py +0 -0
  111. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/config.py +0 -0
  112. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/error_handler.py +0 -0
  113. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/feedback.py +0 -0
  114. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/models.py +0 -0
  115. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/__init__.py +0 -0
  116. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/backup.py +0 -0
  117. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/commands.py +0 -0
  118. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/models.py +0 -0
  119. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/pull_service.py +0 -0
  120. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/update.py +0 -0
  121. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/utils.py +0 -0
  122. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/__init__.py +0 -0
  123. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/__init__.py +0 -0
  124. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/benchmark_runner.py +0 -0
  125. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/exporters.py +0 -0
  126. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/__init__.py +0 -0
  127. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/base.py +0 -0
  128. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/json_formatter.py +0 -0
  129. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/markdown.py +0 -0
  130. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/models.py +0 -0
  131. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/__init__.py +0 -0
  132. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/call_resolution.py +0 -0
  133. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/change_detector.py +0 -0
  134. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/code_retrieval.py +0 -0
  135. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/cypher_models.py +0 -0
  136. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/errors.py +0 -0
  137. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/__init__.py +0 -0
  138. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/base.py +0 -0
  139. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/factory.py +0 -0
  140. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/go/__init__.py +0 -0
  141. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/go/extractor.py +0 -0
  142. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/javascript/__init__.py +0 -0
  143. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/javascript/extractor.py +0 -0
  144. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/protocol.py +0 -0
  145. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/python/__init__.py +0 -0
  146. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/python/extractor.py +0 -0
  147. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/rust/__init__.py +0 -0
  148. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/rust/extractor.py +0 -0
  149. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/types.py +0 -0
  150. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/typescript/__init__.py +0 -0
  151. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/typescript/extractor.py +0 -0
  152. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/gitignore.py +0 -0
  153. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/ingestor.py +0 -0
  154. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/kuzu_compat.py +0 -0
  155. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/language_config.py +0 -0
  156. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/manager.py +0 -0
  157. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/metrics_collector.py +0 -0
  158. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/metrics_types.py +0 -0
  159. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/nl_query.py +0 -0
  160. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/parallel_executor.py +0 -0
  161. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/parser_loader.py +0 -0
  162. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/work_distributor.py +0 -0
  163. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/worker.py +0 -0
  164. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/indexing_state.py +0 -0
  165. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/models.py +0 -0
  166. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/service.py +0 -0
  167. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/exceptions.py +0 -0
  168. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/__init__.py +0 -0
  169. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/client.py +0 -0
  170. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/clients.py +0 -0
  171. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/constants.py +0 -0
  172. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/models.py +0 -0
  173. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/logging_config.py +0 -0
  174. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/posthog_telemetry.py +0 -0
  175. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/__init__.py +0 -0
  176. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/__init__.py +0 -0
  177. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/export.j2 +0 -0
  178. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/file_read.j2 +0 -0
  179. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
  180. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +0 -0
  181. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
  182. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -0
  183. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/router_delegation_mode.j2 +0 -0
  184. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/plan.j2 +0 -0
  185. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/research.j2 +0 -0
  186. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/router.j2 +0 -0
  187. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/specify.j2 +0 -0
  188. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
  189. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/state/system_state.j2 +0 -0
  190. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/tasks.j2 +0 -0
  191. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/__init__.py +0 -0
  192. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
  193. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
  194. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
  195. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
  196. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
  197. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
  198. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/__init__.py +0 -0
  199. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/chunk_summarization.j2 +0 -0
  200. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/combine_summaries.j2 +0 -0
  201. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
  202. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/summarization.j2 +0 -0
  203. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/loader.py +0 -0
  204. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/tools/web_search.j2 +0 -0
  205. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/py.typed +0 -0
  206. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/__init__.py +0 -0
  207. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/codebase.py +0 -0
  208. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/exceptions.py +0 -0
  209. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/models.py +0 -0
  210. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/services.py +0 -0
  211. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/__init__.py +0 -0
  212. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/client.py +0 -0
  213. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/constants.py +0 -0
  214. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/exceptions.py +0 -0
  215. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/models.py +0 -0
  216. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/__init__.py +0 -0
  217. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/file_scanner.py +0 -0
  218. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/hasher.py +0 -0
  219. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/models.py +0 -0
  220. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/upload_pipeline.py +0 -0
  221. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/utils.py +0 -0
  222. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/specs_client.py +0 -0
  223. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/supabase_client.py +0 -0
  224. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/telemetry.py +0 -0
  225. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/__init__.py +0 -0
  226. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/commands/__init__.py +0 -0
  227. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/attachment_bar.py +0 -0
  228. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/mode_indicator.py +0 -0
  229. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/prompt_input.py +0 -0
  230. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/spinner.py +0 -0
  231. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/splash.py +0 -0
  232. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/status_bar.py +0 -0
  233. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/update_indicator.py +0 -0
  234. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/vertical_tail.py +0 -0
  235. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/containers.py +0 -0
  236. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/dependencies.py +0 -0
  237. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/filtered_codebase_service.py +0 -0
  238. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/layout.py +0 -0
  239. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/protocols.py +0 -0
  240. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/__init__.py +0 -0
  241. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/chat.tcss +0 -0
  242. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/chat_screen.py +0 -0
  243. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/codebase_index_prompt_screen.py +0 -0
  244. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/codebase_index_selection.py +0 -0
  245. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/help_text.py +0 -0
  246. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/prompt_history.py +0 -0
  247. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat.tcss +0 -0
  248. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
  249. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/attachment_hint.py +0 -0
  250. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/hint_message.py +0 -0
  251. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/__init__.py +0 -0
  252. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/agent_response.py +0 -0
  253. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/chat_history.py +0 -0
  254. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/formatters.py +0 -0
  255. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/partial_response.py +0 -0
  256. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/user_question.py +0 -0
  257. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/messages.py +0 -0
  258. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/confirmation_dialog.py +0 -0
  259. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/database_locked_dialog.py +0 -0
  260. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/database_timeout_dialog.py +0 -0
  261. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/directory_setup.py +0 -0
  262. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/feedback.py +0 -0
  263. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/github_issue.py +0 -0
  264. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/kuzu_error_dialog.py +0 -0
  265. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/model_picker.py +0 -0
  266. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/models.py +0 -0
  267. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/pipx_migration.py +0 -0
  268. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/provider_config.py +0 -0
  269. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/__init__.py +0 -0
  270. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/create_spec_dialog.py +0 -0
  271. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/models.py +0 -0
  272. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/share_specs_dialog.py +0 -0
  273. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/upload_progress_screen.py +0 -0
  274. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shotgun_auth.py +0 -0
  275. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/spec_pull.py +0 -0
  276. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/splash.py +0 -0
  277. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/welcome.py +0 -0
  278. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/services/__init__.py +0 -0
  279. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/services/conversation_service.py +0 -0
  280. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/state/__init__.py +0 -0
  281. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/state/processing_state.py +0 -0
  282. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/styles.tcss +0 -0
  283. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/templates/app_index.html +0 -0
  284. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/utils/__init__.py +0 -0
  285. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/utils/mode_progress.py +0 -0
  286. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/__init__.py +0 -0
  287. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/approval_widget.py +0 -0
  288. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/cascade_confirmation_widget.py +0 -0
  289. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/plan_panel.py +0 -0
  290. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/step_checkpoint_widget.py +0 -0
  291. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/__init__.py +0 -0
  292. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/datetime_utils.py +0 -0
  293. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/env_utils.py +0 -0
  294. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/file_system_utils.py +0 -0
  295. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/marketing.py +0 -0
  296. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/source_detection.py +0 -0
  297. {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/update_checker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shotgun-sh
3
- Version: 0.7.3.dev1
3
+ Version: 0.7.3.dev2
4
4
  Summary: AI-powered research, planning, and task management CLI tool
5
5
  Project-URL: Homepage, https://shotgun.sh/
6
6
  Project-URL: Repository, https://github.com/shotgun-sh/shotgun
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "shotgun-sh"
3
- version = "0.7.3.dev1"
3
+ version = "0.7.3.dev2"
4
4
  description = "AI-powered research, planning, and task management CLI tool"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -704,17 +704,26 @@ class ConfigManager:
704
704
  def _get_provider_config(
705
705
  self, config: ShotgunConfig, provider: ProviderType
706
706
  ) -> Any:
707
- """Retrieve the provider-specific configuration section."""
707
+ """Retrieve the provider-specific configuration section.
708
+
709
+ Returns None for OPENAI_COMPATIBLE since it uses environment variables
710
+ instead of config file.
711
+ """
708
712
  if provider == ProviderType.OPENAI:
709
713
  return config.openai
710
714
  if provider == ProviderType.ANTHROPIC:
711
715
  return config.anthropic
712
716
  if provider == ProviderType.GOOGLE:
713
717
  return config.google
718
+ if provider == ProviderType.OPENAI_COMPATIBLE:
719
+ # OPENAI_COMPATIBLE uses env vars (SHOTGUN_OPENAI_COMPAT_*), not config
720
+ return None
714
721
  raise ValueError(f"Unsupported provider: {provider}")
715
722
 
716
723
  def _provider_has_api_key(self, provider_config: Any) -> bool:
717
724
  """Return True if the provider config contains a usable API key."""
725
+ if provider_config is None:
726
+ return False
718
727
  api_key = getattr(provider_config, API_KEY_FIELD, None)
719
728
  if api_key is None:
720
729
  return False
@@ -13,6 +13,7 @@ class ProviderType(StrEnum):
13
13
  OPENAI = "openai"
14
14
  ANTHROPIC = "anthropic"
15
15
  GOOGLE = "google"
16
+ OPENAI_COMPATIBLE = "openai_compatible"
16
17
 
17
18
 
18
19
  class KeyProvider(StrEnum):
@@ -51,8 +52,8 @@ class ModelSpec(BaseModel):
51
52
  class ModelConfig(BaseModel):
52
53
  """A fully configured model with API key and settings."""
53
54
 
54
- name: ModelName # Model identifier
55
- provider: ProviderType # Actual LLM provider (openai, anthropic, google)
55
+ name: ModelName | str # Model identifier (str for OpenAI-compatible endpoints)
56
+ provider: ProviderType # Actual LLM provider (openai, anthropic, google, openai_compatible)
56
57
  key_provider: KeyProvider # Authentication method (byok or shotgun)
57
58
  max_input_tokens: int
58
59
  max_output_tokens: int
@@ -77,15 +78,28 @@ class ModelConfig(BaseModel):
77
78
  )
78
79
  return self._model_instance
79
80
 
81
+ @property
82
+ def name_str(self) -> str:
83
+ """Get the model name as a string.
84
+
85
+ Handles both ModelName enum and plain string (for OpenAI-compatible).
86
+ """
87
+ if isinstance(self.name, str):
88
+ return self.name
89
+ return self.name.value
90
+
80
91
  @property
81
92
  def pydantic_model_name(self) -> str:
82
93
  """Compute the full Pydantic AI model identifier. For backward compatibility."""
94
+ if self.provider == ProviderType.OPENAI_COMPATIBLE:
95
+ # For OpenAI-compatible endpoints, use openai prefix with the model name
96
+ return f"openai:{self.name_str}"
83
97
  provider_prefix = {
84
98
  ProviderType.OPENAI: "openai",
85
99
  ProviderType.ANTHROPIC: "anthropic",
86
100
  ProviderType.GOOGLE: "google-gla",
87
101
  }
88
- return f"{provider_prefix[self.provider]}:{self.name}"
102
+ return f"{provider_prefix[self.provider]}:{self.name_str}"
89
103
 
90
104
  @property
91
105
  def is_shotgun_account(self) -> bool:
@@ -31,7 +31,60 @@ from .streaming_test import check_streaming_capability
31
31
  logger = get_logger(__name__)
32
32
 
33
33
  # Global cache for Model instances (singleton pattern)
34
- _model_cache: dict[tuple[ProviderType, KeyProvider, ModelName, str], Model] = {}
34
+ _model_cache: dict[tuple[ProviderType, KeyProvider, ModelName | str, str], Model] = {}
35
+
36
+ # Module-level model override for OpenAI-compatible mode (set via --model CLI flag)
37
+ _openai_compat_model_override: str | None = None
38
+
39
+ # Default model for OpenAI-compatible endpoints
40
+ OPENAI_COMPAT_DEFAULT_MODEL = "gpt-5.2"
41
+
42
+
43
+ def set_openai_compat_model(model: str | None) -> None:
44
+ """Set the model override for OpenAI-compatible endpoints.
45
+
46
+ This is called by the CLI when --model is specified.
47
+
48
+ Args:
49
+ model: Model name to use, or None to use the default.
50
+ """
51
+ global _openai_compat_model_override
52
+ _openai_compat_model_override = model
53
+
54
+
55
+ def _create_openai_compat_model(
56
+ api_key: str, model_name: str, max_tokens: int
57
+ ) -> Model:
58
+ """Create a model for OpenAI-compatible endpoints.
59
+
60
+ Uses the SHOTGUN_OPENAI_COMPAT_BASE_URL from settings to configure
61
+ the LiteLLM provider with a custom base URL.
62
+
63
+ Args:
64
+ api_key: API key for the endpoint
65
+ model_name: Name of the model to use
66
+ max_tokens: Maximum output tokens
67
+
68
+ Returns:
69
+ Configured OpenAI-compatible Model instance
70
+ """
71
+ from shotgun.settings import settings
72
+
73
+ base_url = settings.openai_compat.base_url
74
+ if not base_url:
75
+ raise ValueError(
76
+ "SHOTGUN_OPENAI_COMPAT_BASE_URL is required for OpenAI-compatible mode"
77
+ )
78
+
79
+ # Use OpenAI provider with custom base_url
80
+ openai_provider = OpenAIProvider(api_key=api_key, base_url=base_url)
81
+
82
+ # Use OpenAIChatModel for broad compatibility with OpenAI-compatible APIs
83
+ return OpenAIChatModel(
84
+ model_name,
85
+ provider=openai_provider,
86
+ settings=ModelSettings(max_tokens=max_tokens),
87
+ )
35
88
 
36
89
 
37
90
  def get_default_model_for_provider(config: ShotgunConfig) -> ModelName:
@@ -65,7 +118,7 @@ def get_default_model_for_provider(config: ShotgunConfig) -> ModelName:
65
118
  def get_or_create_model(
66
119
  provider: ProviderType,
67
120
  key_provider: "KeyProvider",
68
- model_name: ModelName,
121
+ model_name: ModelName | str,
69
122
  api_key: str,
70
123
  ) -> Model:
71
124
  """Get or create a singleton Model instance.
@@ -92,8 +145,8 @@ def get_or_create_model(
92
145
  model_name,
93
146
  )
94
147
 
95
- # Get max_tokens from MODEL_SPECS
96
- if model_name in MODEL_SPECS:
148
+ # Get max_tokens from MODEL_SPECS (only for known models)
149
+ if isinstance(model_name, ModelName) and model_name in MODEL_SPECS:
97
150
  max_tokens = MODEL_SPECS[model_name].max_output_tokens
98
151
  else:
99
152
  # Fallback defaults based on provider
@@ -101,9 +154,24 @@ def get_or_create_model(
101
154
  ProviderType.OPENAI: 16_000,
102
155
  ProviderType.ANTHROPIC: 32_000,
103
156
  ProviderType.GOOGLE: 64_000,
157
+ ProviderType.OPENAI_COMPATIBLE: 16_000,
104
158
  }.get(provider, 16_000)
105
159
 
160
+ # Handle OpenAI-compatible endpoints (uses settings for base_url)
161
+ if provider == ProviderType.OPENAI_COMPATIBLE:
162
+ _model_cache[cache_key] = _create_openai_compat_model(
163
+ api_key, str(model_name), max_tokens
164
+ )
165
+ return _model_cache[cache_key]
166
+
106
167
  # Use LiteLLM proxy for Shotgun Account, native providers for BYOK
168
+ # At this point, model_name must be a ModelName (string handled above via OPENAI_COMPATIBLE)
169
+ if not isinstance(model_name, ModelName):
170
+ raise ValueError(
171
+ f"Unknown model name: {model_name}. "
172
+ "For custom models, set SHOTGUN_OPENAI_COMPAT_BASE_URL."
173
+ )
174
+
107
175
  if key_provider == KeyProvider.SHOTGUN:
108
176
  # Shotgun Account uses LiteLLM proxy with native model types where possible
109
177
  if model_name in MODEL_SPECS:
@@ -192,7 +260,38 @@ async def get_provider_model(
192
260
 
193
261
  Raises:
194
262
  ValueError: If provider is not configured properly or model not found
263
+
264
+ Note:
265
+ When SHOTGUN_OPENAI_COMPAT_BASE_URL is set, this function bypasses all
266
+ other provider configuration and uses the OpenAI-compatible endpoint.
267
+ The model name comes from SHOTGUN_OPENAI_COMPAT_DEFAULT_MODEL (default: gpt-4).
195
268
  """
269
+ from shotgun.settings import settings
270
+
271
+ # PRIORITY 0: Check for OpenAI-compatible mode
272
+ # When both SHOTGUN_OPENAI_COMPAT_BASE_URL and API_KEY are set, bypass all other providers
273
+ if settings.openai_compat.base_url and settings.openai_compat.api_key:
274
+ compat_api_key = settings.openai_compat.api_key
275
+
276
+ # Use CLI override if set, otherwise use hardcoded default
277
+ model_name = _openai_compat_model_override or OPENAI_COMPAT_DEFAULT_MODEL
278
+
279
+ logger.info(
280
+ "Using OpenAI-compatible endpoint: %s with model: %s",
281
+ settings.openai_compat.base_url,
282
+ model_name,
283
+ )
284
+
285
+ return ModelConfig(
286
+ name=model_name,
287
+ provider=ProviderType.OPENAI_COMPATIBLE,
288
+ key_provider=KeyProvider.BYOK,
289
+ max_input_tokens=128_000, # Reasonable default for OpenAI-compatible
290
+ max_output_tokens=16_000,
291
+ api_key=compat_api_key,
292
+ supports_streaming=True,
293
+ )
294
+
196
295
  config_manager = get_config_manager()
197
296
  # Use cached config for read-only access (performance)
198
297
  config = await config_manager.load(force_reload=False)
@@ -414,7 +414,7 @@ class ContextAnalyzer:
414
414
  total_messages=total_messages,
415
415
  context_window=self.model_config.max_input_tokens,
416
416
  agent_context_tokens=agent_context_tokens,
417
- model_name=self.model_config.name.value,
417
+ model_name=self.model_config.name_str,
418
418
  max_usable_tokens=max_usable_tokens,
419
419
  free_space_tokens=free_space_tokens,
420
420
  )
@@ -53,7 +53,7 @@ async def apply_persistent_compaction(
53
53
  {
54
54
  "tokens_saved_estimate": tokens_saved,
55
55
  "retention_window": 3,
56
- "model_name": deps.llm_model.name.value,
56
+ "model_name": deps.llm_model.name_str,
57
57
  },
58
58
  )
59
59
 
@@ -98,7 +98,7 @@ async def apply_persistent_compaction(
98
98
  if hasattr(deps, "agent_mode") and deps.agent_mode
99
99
  else "unknown",
100
100
  # Model and provider info (no computation needed)
101
- "model_name": deps.llm_model.name.value,
101
+ "model_name": deps.llm_model.name_str,
102
102
  "provider": deps.llm_model.provider.value,
103
103
  "key_provider": deps.llm_model.key_provider.value,
104
104
  },
@@ -449,7 +449,7 @@ async def token_limit_compactor(
449
449
  if hasattr(deps, "agent_mode") and deps.agent_mode
450
450
  else "unknown",
451
451
  # Model and provider info (no computation needed)
452
- "model_name": deps.llm_model.name.value,
452
+ "model_name": deps.llm_model.name_str,
453
453
  "provider": deps.llm_model.provider.value,
454
454
  "key_provider": deps.llm_model.key_provider.value,
455
455
  },
@@ -614,7 +614,7 @@ async def _full_compaction(
614
614
  if hasattr(deps, "agent_mode") and deps.agent_mode
615
615
  else "unknown",
616
616
  # Model and provider info (no computation needed)
617
- "model_name": deps.llm_model.name.value,
617
+ "model_name": deps.llm_model.name_str,
618
618
  "provider": deps.llm_model.provider.value,
619
619
  "key_provider": deps.llm_model.key_provider.value,
620
620
  },
@@ -686,7 +686,7 @@ async def _chunked_compaction(
686
686
  1 for s in chunk_summaries if not s.startswith("[Chunk")
687
687
  ),
688
688
  "retention_window_size": len(retained_messages),
689
- "model_name": deps.llm_model.name.value,
689
+ "model_name": deps.llm_model.name_str,
690
690
  "provider": deps.llm_model.provider.value,
691
691
  },
692
692
  )
@@ -54,6 +54,10 @@ def get_token_counter(model_config: ModelConfig) -> TokenCounter:
54
54
  counter: TokenCounter
55
55
  if model_config.provider == ProviderType.OPENAI:
56
56
  counter = OpenAITokenCounter(model_config.name)
57
+ elif model_config.provider == ProviderType.OPENAI_COMPATIBLE:
58
+ # Use OpenAI token counter for OpenAI-compatible endpoints
59
+ # Fall back to a reasonable default model for tokenization
60
+ counter = OpenAITokenCounter(str(model_config.name))
57
61
  elif model_config.provider == ProviderType.ANTHROPIC:
58
62
  counter = AnthropicTokenCounter(
59
63
  model_config.name, model_config.api_key, model_config.key_provider
@@ -4,6 +4,7 @@ Provides web search capabilities for multiple LLM providers:
4
4
  - OpenAI: Uses Responses API with web_search tool
5
5
  - Anthropic: Uses Messages API with web_search_20250305 tool
6
6
  - Gemini: Uses grounding with Google Search via Pydantic AI
7
+ - OpenAI-compatible: Uses Responses API via custom endpoint (e.g., LiteLLM proxy)
7
8
 
8
9
  Web search uses the provider matching the user's selected model for consistency.
9
10
  """
@@ -13,10 +14,12 @@ from collections.abc import Awaitable, Callable
13
14
  from shotgun.agents.config.manager import get_config_manager
14
15
  from shotgun.agents.config.models import MODEL_SPECS, ProviderType
15
16
  from shotgun.logging_config import get_logger
17
+ from shotgun.settings import settings
16
18
 
17
19
  from .anthropic import anthropic_web_search_tool
18
20
  from .gemini import gemini_web_search_tool
19
21
  from .openai import openai_web_search_tool
22
+ from .openai_compatible import openai_compatible_web_search_tool
20
23
  from .utils import is_provider_available
21
24
 
22
25
  logger = get_logger(__name__)
@@ -29,6 +32,7 @@ _PROVIDER_WEB_SEARCH_TOOLS: dict[ProviderType, WebSearchTool] = {
29
32
  ProviderType.OPENAI: openai_web_search_tool,
30
33
  ProviderType.ANTHROPIC: anthropic_web_search_tool,
31
34
  ProviderType.GOOGLE: gemini_web_search_tool,
35
+ ProviderType.OPENAI_COMPATIBLE: openai_compatible_web_search_tool,
32
36
  }
33
37
 
34
38
 
@@ -41,7 +45,12 @@ async def get_available_web_search_tools() -> list[WebSearchTool]:
41
45
  Returns:
42
46
  List containing the preferred web search tool, or empty if none available
43
47
  """
44
- logger.debug("🔍 Checking available web search tools")
48
+ logger.debug("Checking available web search tools")
49
+
50
+ # Priority 0: Check for OpenAI-compatible mode
51
+ if settings.openai_compat.base_url and settings.openai_compat.api_key:
52
+ logger.info("Using OpenAI-compatible web search (openai_compat mode enabled)")
53
+ return [openai_compatible_web_search_tool]
45
54
 
46
55
  # Get user's selected model to determine preferred provider
47
56
  config_manager = get_config_manager()
@@ -60,18 +69,21 @@ async def get_available_web_search_tools() -> list[WebSearchTool]:
60
69
  if preferred_provider and await is_provider_available(preferred_provider):
61
70
  tool = _PROVIDER_WEB_SEARCH_TOOLS[preferred_provider]
62
71
  logger.info(
63
- "🔍 Using %s web search (matches selected model)", preferred_provider.value
72
+ "Using %s web search (matches selected model)", preferred_provider.value
64
73
  )
65
74
  return [tool]
66
75
 
67
76
  # Fall back to any available provider
68
77
  for provider in ProviderType:
78
+ if provider == ProviderType.OPENAI_COMPATIBLE:
79
+ # Skip OPENAI_COMPATIBLE in fallback - it's handled above
80
+ continue
69
81
  if await is_provider_available(provider):
70
82
  tool = _PROVIDER_WEB_SEARCH_TOOLS[provider]
71
- logger.info("🔍 Using %s web search (fallback)", provider.value)
83
+ logger.info("Using %s web search (fallback)", provider.value)
72
84
  return [tool]
73
85
 
74
- logger.warning("⚠️ No web search tools available - no API keys configured")
86
+ logger.warning("No web search tools available - no API keys configured")
75
87
  return []
76
88
 
77
89
 
@@ -79,6 +91,7 @@ __all__ = [
79
91
  "openai_web_search_tool",
80
92
  "anthropic_web_search_tool",
81
93
  "gemini_web_search_tool",
94
+ "openai_compatible_web_search_tool",
82
95
  "get_available_web_search_tools",
83
96
  "is_provider_available",
84
97
  "WebSearchTool",
@@ -0,0 +1,136 @@
1
+ """OpenAI-compatible endpoint web search tool implementation."""
2
+
3
+ import asyncio
4
+
5
+ from openai import AsyncOpenAI
6
+ from opentelemetry import trace
7
+
8
+ from shotgun.agents.tools.registry import ToolCategory, register_tool
9
+ from shotgun.logging_config import get_logger
10
+ from shotgun.prompts import PromptLoader
11
+ from shotgun.settings import settings
12
+ from shotgun.utils.datetime_utils import get_datetime_context
13
+
14
+ logger = get_logger(__name__)
15
+
16
+ # Global prompt loader instance
17
+ prompt_loader = PromptLoader()
18
+
19
+ # Timeout for web search API call (in seconds)
20
+ WEB_SEARCH_TIMEOUT = 120 # 2 minutes
21
+
22
+ # Default model for web search if not configured
23
+ DEFAULT_WEB_SEARCH_MODEL = "openai/gpt-5.2"
24
+
25
+
26
+ @register_tool(
27
+ category=ToolCategory.WEB_RESEARCH,
28
+ display_text="Searching web",
29
+ key_arg="query",
30
+ )
31
+ async def openai_compatible_web_search_tool(query: str) -> str:
32
+ """Perform a web search using an OpenAI-compatible endpoint.
33
+
34
+ This tool uses OpenAI's Responses API with web_search capabilities
35
+ via the configured OpenAI-compatible endpoint (e.g., LiteLLM proxy).
36
+
37
+ Args:
38
+ query: The search query
39
+
40
+ Returns:
41
+ Search results as a formatted string
42
+ """
43
+ logger.debug("Invoking OpenAI-compatible web_search_tool with query: %s", query)
44
+
45
+ span = trace.get_current_span()
46
+ span.set_attribute("input.value", f"**Query:** {query}\n")
47
+
48
+ try:
49
+ base_url = settings.openai_compat.base_url
50
+ api_key = settings.openai_compat.api_key
51
+
52
+ if not base_url or not api_key:
53
+ error_msg = "OpenAI-compatible endpoint not configured"
54
+ logger.error(error_msg)
55
+ span.set_attribute("output.value", f"**Error:**\n {error_msg}\n")
56
+ return error_msg
57
+
58
+ # Get datetime context for the search prompt
59
+ dt_context = get_datetime_context()
60
+
61
+ # Render search prompt from template
62
+ prompt = prompt_loader.render(
63
+ "tools/web_search.j2",
64
+ query=query,
65
+ current_datetime=dt_context.datetime_formatted,
66
+ timezone_name=dt_context.timezone_name,
67
+ utc_offset=dt_context.utc_offset,
68
+ )
69
+
70
+ # Use configured web search model or default
71
+ web_search_model = (
72
+ settings.openai_compat.web_search_model or DEFAULT_WEB_SEARCH_MODEL
73
+ )
74
+
75
+ logger.debug(
76
+ "Using OpenAI-compatible endpoint for web search: %s with model %s",
77
+ base_url,
78
+ web_search_model,
79
+ )
80
+
81
+ client = AsyncOpenAI(api_key=api_key, base_url=base_url)
82
+
83
+ # Wrap API call with timeout to prevent indefinite hangs
84
+ try:
85
+ response = await asyncio.wait_for(
86
+ client.responses.create(
87
+ model=web_search_model,
88
+ input=[
89
+ {
90
+ "role": "user",
91
+ "content": [{"type": "input_text", "text": prompt}],
92
+ }
93
+ ],
94
+ text={
95
+ "format": {"type": "text"},
96
+ "verbosity": "high",
97
+ },
98
+ reasoning={"effort": "medium", "summary": "auto"},
99
+ tools=[
100
+ {
101
+ "type": "web_search",
102
+ "user_location": {"type": "approximate"},
103
+ "search_context_size": "high",
104
+ }
105
+ ],
106
+ store=False,
107
+ include=[
108
+ "reasoning.encrypted_content",
109
+ "web_search_call.action.sources", # pyright: ignore[reportArgumentType]
110
+ ],
111
+ ),
112
+ timeout=WEB_SEARCH_TIMEOUT,
113
+ )
114
+ except asyncio.TimeoutError:
115
+ error_msg = f"Web search timed out after {WEB_SEARCH_TIMEOUT} seconds"
116
+ logger.warning(error_msg)
117
+ span.set_attribute("output.value", f"**Error:**\n {error_msg}\n")
118
+ return error_msg
119
+
120
+ result_text = response.output_text or "No content returned"
121
+
122
+ logger.debug("Web search result: %d characters", len(result_text))
123
+ logger.debug(
124
+ "Result preview: %s...",
125
+ result_text[:100] if result_text else "No result",
126
+ )
127
+
128
+ span.set_attribute("output.value", f"**Results:**\n {result_text}\n")
129
+
130
+ return result_text
131
+ except Exception as e:
132
+ error_msg = f"Error performing web search: {str(e)}"
133
+ logger.error("Web search failed: %s", str(e))
134
+ logger.debug("Full error details: %s", error_msg)
135
+ span.set_attribute("output.value", f"**Error:**\n {error_msg}\n")
136
+ return error_msg
@@ -96,7 +96,7 @@ async def analyze_context() -> ContextAnalysisOutput:
96
96
  model_config = await get_provider_model()
97
97
 
98
98
  # Debug: Log the model being used
99
- logger.debug(f"Using model: {model_config.name.value}")
99
+ logger.debug(f"Using model: {model_config.name_str}")
100
100
  logger.debug(f"Provider: {model_config.provider.value}")
101
101
  logger.debug(f"Key provider: {model_config.key_provider.value}")
102
102
  logger.debug(f"Max input tokens: {model_config.max_input_tokens}")
@@ -37,6 +37,14 @@ def run(
37
37
  ProviderType | None,
38
38
  typer.Option("--provider", "-p", help="AI provider to use (overrides default)"),
39
39
  ] = None,
40
+ model: Annotated[
41
+ str | None,
42
+ typer.Option(
43
+ "--model",
44
+ "-m",
45
+ help="Model name to use (requires SHOTGUN_OPENAI_COMPAT_BASE_URL to be set)",
46
+ ),
47
+ ] = None,
40
48
  ) -> None:
41
49
  """Execute a prompt using the Router agent in drafting mode.
42
50
 
@@ -45,6 +53,12 @@ def run(
45
53
  """
46
54
  logger.info("Running prompt: %s", prompt[:100])
47
55
 
56
+ # If --model is specified, set it for OpenAI-compatible mode
57
+ if model:
58
+ from shotgun.agents.config.provider import set_openai_compat_model
59
+
60
+ set_openai_compat_model(model)
61
+
48
62
  try:
49
63
  asyncio.run(async_run(prompt, non_interactive, provider))
50
64
  except Exception as e:
@@ -165,6 +165,14 @@ def main(
165
165
  help="Force re-indexing of codebase (ignores existing index)",
166
166
  ),
167
167
  ] = False,
168
+ model: Annotated[
169
+ str | None,
170
+ typer.Option(
171
+ "--model",
172
+ "-m",
173
+ help="Model name to use (requires SHOTGUN_OPENAI_COMPAT_BASE_URL to be set)",
174
+ ),
175
+ ] = None,
168
176
  ) -> None:
169
177
  """Shotgun - AI-powered CLI tool."""
170
178
  logger.debug("Starting shotgun CLI application")
@@ -174,6 +182,12 @@ def main(
174
182
  perform_auto_update_async(no_update_check=no_update_check)
175
183
 
176
184
  if ctx.invoked_subcommand is None and not ctx.resilient_parsing:
185
+ # If --model is specified, set it for OpenAI-compatible mode
186
+ if model:
187
+ from shotgun.agents.config.provider import set_openai_compat_model
188
+
189
+ set_openai_compat_model(model)
190
+
177
191
  if web:
178
192
  logger.debug("Launching shotgun TUI as web application")
179
193
  try:
@@ -184,6 +198,7 @@ def main(
184
198
  no_update_check=no_update_check,
185
199
  continue_session=continue_session,
186
200
  force_reindex=force_reindex,
201
+ model_override=model, # Passed to construct command line for spawned process
187
202
  )
188
203
  finally:
189
204
  # Ensure PostHog is shut down cleanly even if server exits unexpectedly
@@ -241,6 +241,39 @@ class IndexingSettings(BaseSettings):
241
241
  return bool(v)
242
242
 
243
243
 
244
+ class OpenAICompatSettings(BaseSettings):
245
+ """OpenAI-compatible endpoint settings.
246
+
247
+ When base_url is set, Shotgun bypasses normal provider configuration
248
+ and uses the specified endpoint directly for all LLM requests.
249
+
250
+ Environment variables:
251
+ SHOTGUN_OPENAI_COMPAT_BASE_URL: The base URL of the OpenAI-compatible endpoint
252
+ SHOTGUN_OPENAI_COMPAT_API_KEY: API key for authentication
253
+ SHOTGUN_OPENAI_COMPAT_WEB_SEARCH_MODEL: Model to use for web search (optional)
254
+ """
255
+
256
+ base_url: str | None = Field(
257
+ default=None,
258
+ description="Base URL for OpenAI-compatible endpoint (e.g., https://api.example.com/v1)",
259
+ )
260
+ api_key: str | None = Field(
261
+ default=None,
262
+ description="API key for the OpenAI-compatible endpoint",
263
+ )
264
+ web_search_model: str | None = Field(
265
+ default=None,
266
+ description="Model to use for web search (defaults to openai/gpt-5.2 if not set)",
267
+ )
268
+
269
+ model_config = SettingsConfigDict(
270
+ env_prefix="SHOTGUN_OPENAI_COMPAT_",
271
+ env_file=".env",
272
+ env_file_encoding="utf-8",
273
+ extra="ignore",
274
+ )
275
+
276
+
244
277
  class Settings(BaseSettings):
245
278
  """Main application settings with SHOTGUN_ prefix.
246
279
 
@@ -276,6 +309,7 @@ class Settings(BaseSettings):
276
309
  api: ApiSettings = Field(default_factory=ApiSettings)
277
310
  dev: DevelopmentSettings = Field(default_factory=DevelopmentSettings)
278
311
  indexing: IndexingSettings = Field(default_factory=IndexingSettings)
312
+ openai_compat: OpenAICompatSettings = Field(default_factory=OpenAICompatSettings)
279
313
 
280
314
  model_config = SettingsConfigDict(
281
315
  env_prefix="SHOTGUN_",