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.
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/PKG-INFO +1 -1
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/pyproject.toml +1 -1
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/manager.py +10 -1
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/models.py +17 -3
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/provider.py +103 -4
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/analyzer.py +1 -1
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/compaction.py +2 -2
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/history_processors.py +3 -3
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/utils.py +4 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/__init__.py +17 -4
- shotgun_sh-0.7.3.dev2/src/shotgun/agents/tools/web_search/openai_compatible.py +136 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/context.py +1 -1
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/run.py +14 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/main.py +15 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/settings.py +34 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/app.py +18 -2
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/context_indicator.py +24 -14
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/command_providers.py +48 -20
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/widget_coordinator.py +3 -5
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/.gitignore +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/LICENSE +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/README.md +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/hatch_build.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/agent_manager.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/cancellation.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/common.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/README.md +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/config/streaming_test.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/formatter.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/filters.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/chunking.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/context_extraction.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/file_content_deduplication.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/history_building.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/message_utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/anthropic.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/base.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/openai.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/sentencepiece_counter.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_counting/tokenizer_cache.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/history/token_estimation.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/manager.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/conversation/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/error/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/error/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/export.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/file_read.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/gemini3_patch.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/llm.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/messages.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/plan.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/research.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/router.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/delegation_tools.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/router/tools/plan_tools.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/runner.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/specify.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tasks.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/file_management.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/file_read_tools/__init__.py +0 -0
- {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
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/insert_section.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/remove_section.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/replace_section.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/markdown_tools/utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/mermaid_validation.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/registry.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/openai.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/usage_manager.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/api_endpoints.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/errors.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/parser.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/attachments/processor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/build_constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/clear.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/commands.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/codebase/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/compact.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/config.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/error_handler.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/feedback.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/backup.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/commands.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/spec/pull_service.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/update.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/cli/utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/benchmark_runner.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/exporters.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/base.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/json_formatter.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/formatters/markdown.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/benchmarks/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/call_resolution.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/change_detector.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/code_retrieval.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/cypher_models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/errors.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/base.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/factory.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/go/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/go/extractor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/javascript/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/javascript/extractor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/protocol.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/python/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/python/extractor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/rust/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/rust/extractor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/types.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/typescript/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/extractors/typescript/extractor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/gitignore.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/ingestor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/kuzu_compat.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/language_config.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/manager.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/metrics_collector.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/metrics_types.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/nl_query.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/parallel_executor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/parser_loader.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/work_distributor.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/core/worker.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/indexing_state.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/codebase/service.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/exceptions.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/client.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/clients.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/llm_proxy/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/logging_config.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/posthog_telemetry.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/export.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/file_read.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/partials/router_delegation_mode.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/plan.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/research.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/router.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/specify.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/state/system_state.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/agents/tasks.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/chunk_summarization.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/combine_summaries.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/history/summarization.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/loader.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/prompts/tools/web_search.j2 +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/py.typed +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/codebase.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/exceptions.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/sdk/services.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/client.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/constants.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/exceptions.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/file_scanner.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/hasher.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/upload_pipeline.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/shared_specs/utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/specs_client.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/shotgun_web/supabase_client.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/telemetry.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/commands/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/attachment_bar.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/mode_indicator.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/prompt_input.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/spinner.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/splash.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/status_bar.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/update_indicator.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/components/vertical_tail.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/containers.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/dependencies.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/filtered_codebase_service.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/layout.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/protocols.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/chat.tcss +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/chat_screen.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/codebase_index_prompt_screen.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/codebase_index_selection.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/help_text.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat/prompt_history.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat.tcss +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/attachment_hint.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/hint_message.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/agent_response.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/chat_history.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/formatters.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/partial_response.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/history/user_question.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/chat_screen/messages.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/confirmation_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/database_locked_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/database_timeout_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/directory_setup.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/feedback.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/github_issue.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/kuzu_error_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/model_picker.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/pipx_migration.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/provider_config.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/create_spec_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/models.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/share_specs_dialog.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shared_specs/upload_progress_screen.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/shotgun_auth.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/spec_pull.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/splash.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/screens/welcome.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/services/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/services/conversation_service.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/state/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/state/processing_state.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/styles.tcss +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/templates/app_index.html +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/utils/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/utils/mode_progress.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/approval_widget.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/cascade_confirmation_widget.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/plan_panel.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/tui/widgets/step_checkpoint_widget.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/__init__.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/datetime_utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/env_utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/file_system_utils.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/marketing.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/source_detection.py +0 -0
- {shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/utils/update_checker.py +0 -0
|
@@ -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.
|
|
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)
|
{shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/context_analyzer/analyzer.py
RENAMED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
{shotgun_sh-0.7.3.dev1 → shotgun_sh-0.7.3.dev2}/src/shotgun/agents/tools/web_search/__init__.py
RENAMED
|
@@ -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("
|
|
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
|
-
"
|
|
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("
|
|
83
|
+
logger.info("Using %s web search (fallback)", provider.value)
|
|
72
84
|
return [tool]
|
|
73
85
|
|
|
74
|
-
logger.warning("
|
|
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.
|
|
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_",
|