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