shotgun-sh 0.2.8.dev2__py3-none-any.whl → 0.3.3.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. shotgun/agents/agent_manager.py +382 -60
  2. shotgun/agents/common.py +15 -9
  3. shotgun/agents/config/README.md +89 -0
  4. shotgun/agents/config/__init__.py +10 -1
  5. shotgun/agents/config/constants.py +0 -6
  6. shotgun/agents/config/manager.py +383 -82
  7. shotgun/agents/config/models.py +122 -18
  8. shotgun/agents/config/provider.py +81 -15
  9. shotgun/agents/config/streaming_test.py +119 -0
  10. shotgun/agents/context_analyzer/__init__.py +28 -0
  11. shotgun/agents/context_analyzer/analyzer.py +475 -0
  12. shotgun/agents/context_analyzer/constants.py +9 -0
  13. shotgun/agents/context_analyzer/formatter.py +115 -0
  14. shotgun/agents/context_analyzer/models.py +212 -0
  15. shotgun/agents/conversation/__init__.py +18 -0
  16. shotgun/agents/conversation/filters.py +164 -0
  17. shotgun/agents/conversation/history/chunking.py +278 -0
  18. shotgun/agents/{history → conversation/history}/compaction.py +36 -5
  19. shotgun/agents/{history → conversation/history}/constants.py +5 -0
  20. shotgun/agents/conversation/history/file_content_deduplication.py +216 -0
  21. shotgun/agents/{history → conversation/history}/history_processors.py +380 -8
  22. shotgun/agents/{history → conversation/history}/token_counting/anthropic.py +25 -1
  23. shotgun/agents/{history → conversation/history}/token_counting/base.py +14 -3
  24. shotgun/agents/{history → conversation/history}/token_counting/openai.py +11 -1
  25. shotgun/agents/{history → conversation/history}/token_counting/sentencepiece_counter.py +8 -0
  26. shotgun/agents/{history → conversation/history}/token_counting/tokenizer_cache.py +3 -1
  27. shotgun/agents/{history → conversation/history}/token_counting/utils.py +0 -3
  28. shotgun/agents/{conversation_manager.py → conversation/manager.py} +36 -20
  29. shotgun/agents/{conversation_history.py → conversation/models.py} +8 -92
  30. shotgun/agents/error/__init__.py +11 -0
  31. shotgun/agents/error/models.py +19 -0
  32. shotgun/agents/export.py +2 -2
  33. shotgun/agents/plan.py +2 -2
  34. shotgun/agents/research.py +3 -3
  35. shotgun/agents/runner.py +230 -0
  36. shotgun/agents/specify.py +2 -2
  37. shotgun/agents/tasks.py +2 -2
  38. shotgun/agents/tools/codebase/codebase_shell.py +6 -0
  39. shotgun/agents/tools/codebase/directory_lister.py +6 -0
  40. shotgun/agents/tools/codebase/file_read.py +11 -2
  41. shotgun/agents/tools/codebase/query_graph.py +6 -0
  42. shotgun/agents/tools/codebase/retrieve_code.py +6 -0
  43. shotgun/agents/tools/file_management.py +27 -7
  44. shotgun/agents/tools/registry.py +217 -0
  45. shotgun/agents/tools/web_search/__init__.py +8 -8
  46. shotgun/agents/tools/web_search/anthropic.py +8 -2
  47. shotgun/agents/tools/web_search/gemini.py +7 -1
  48. shotgun/agents/tools/web_search/openai.py +8 -2
  49. shotgun/agents/tools/web_search/utils.py +2 -2
  50. shotgun/agents/usage_manager.py +16 -11
  51. shotgun/api_endpoints.py +7 -3
  52. shotgun/build_constants.py +2 -2
  53. shotgun/cli/clear.py +53 -0
  54. shotgun/cli/compact.py +188 -0
  55. shotgun/cli/config.py +8 -5
  56. shotgun/cli/context.py +154 -0
  57. shotgun/cli/error_handler.py +24 -0
  58. shotgun/cli/export.py +34 -34
  59. shotgun/cli/feedback.py +4 -2
  60. shotgun/cli/models.py +1 -0
  61. shotgun/cli/plan.py +34 -34
  62. shotgun/cli/research.py +18 -10
  63. shotgun/cli/spec/__init__.py +5 -0
  64. shotgun/cli/spec/backup.py +81 -0
  65. shotgun/cli/spec/commands.py +132 -0
  66. shotgun/cli/spec/models.py +48 -0
  67. shotgun/cli/spec/pull_service.py +219 -0
  68. shotgun/cli/specify.py +20 -19
  69. shotgun/cli/tasks.py +34 -34
  70. shotgun/cli/update.py +16 -2
  71. shotgun/codebase/core/change_detector.py +5 -3
  72. shotgun/codebase/core/code_retrieval.py +4 -2
  73. shotgun/codebase/core/ingestor.py +163 -15
  74. shotgun/codebase/core/manager.py +13 -4
  75. shotgun/codebase/core/nl_query.py +1 -1
  76. shotgun/codebase/models.py +2 -0
  77. shotgun/exceptions.py +357 -0
  78. shotgun/llm_proxy/__init__.py +17 -0
  79. shotgun/llm_proxy/client.py +215 -0
  80. shotgun/llm_proxy/models.py +137 -0
  81. shotgun/logging_config.py +60 -27
  82. shotgun/main.py +77 -11
  83. shotgun/posthog_telemetry.py +38 -29
  84. shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +28 -2
  85. shotgun/prompts/agents/partials/interactive_mode.j2 +3 -3
  86. shotgun/prompts/agents/plan.j2 +16 -0
  87. shotgun/prompts/agents/research.j2 +16 -3
  88. shotgun/prompts/agents/specify.j2 +54 -1
  89. shotgun/prompts/agents/state/system_state.j2 +0 -2
  90. shotgun/prompts/agents/tasks.j2 +16 -0
  91. shotgun/prompts/history/chunk_summarization.j2 +34 -0
  92. shotgun/prompts/history/combine_summaries.j2 +53 -0
  93. shotgun/sdk/codebase.py +14 -3
  94. shotgun/sentry_telemetry.py +163 -16
  95. shotgun/settings.py +243 -0
  96. shotgun/shotgun_web/__init__.py +67 -1
  97. shotgun/shotgun_web/client.py +42 -1
  98. shotgun/shotgun_web/constants.py +46 -0
  99. shotgun/shotgun_web/exceptions.py +29 -0
  100. shotgun/shotgun_web/models.py +390 -0
  101. shotgun/shotgun_web/shared_specs/__init__.py +32 -0
  102. shotgun/shotgun_web/shared_specs/file_scanner.py +175 -0
  103. shotgun/shotgun_web/shared_specs/hasher.py +83 -0
  104. shotgun/shotgun_web/shared_specs/models.py +71 -0
  105. shotgun/shotgun_web/shared_specs/upload_pipeline.py +329 -0
  106. shotgun/shotgun_web/shared_specs/utils.py +34 -0
  107. shotgun/shotgun_web/specs_client.py +703 -0
  108. shotgun/shotgun_web/supabase_client.py +31 -0
  109. shotgun/telemetry.py +10 -33
  110. shotgun/tui/app.py +310 -46
  111. shotgun/tui/commands/__init__.py +1 -1
  112. shotgun/tui/components/context_indicator.py +179 -0
  113. shotgun/tui/components/mode_indicator.py +70 -0
  114. shotgun/tui/components/status_bar.py +48 -0
  115. shotgun/tui/containers.py +91 -0
  116. shotgun/tui/dependencies.py +39 -0
  117. shotgun/tui/layout.py +5 -0
  118. shotgun/tui/protocols.py +45 -0
  119. shotgun/tui/screens/chat/__init__.py +5 -0
  120. shotgun/tui/screens/chat/chat.tcss +54 -0
  121. shotgun/tui/screens/chat/chat_screen.py +1531 -0
  122. shotgun/tui/screens/chat/codebase_index_prompt_screen.py +243 -0
  123. shotgun/tui/screens/chat/codebase_index_selection.py +12 -0
  124. shotgun/tui/screens/chat/help_text.py +40 -0
  125. shotgun/tui/screens/chat/prompt_history.py +48 -0
  126. shotgun/tui/screens/chat.tcss +11 -0
  127. shotgun/tui/screens/chat_screen/command_providers.py +91 -4
  128. shotgun/tui/screens/chat_screen/hint_message.py +76 -1
  129. shotgun/tui/screens/chat_screen/history/__init__.py +22 -0
  130. shotgun/tui/screens/chat_screen/history/agent_response.py +66 -0
  131. shotgun/tui/screens/chat_screen/history/chat_history.py +115 -0
  132. shotgun/tui/screens/chat_screen/history/formatters.py +115 -0
  133. shotgun/tui/screens/chat_screen/history/partial_response.py +43 -0
  134. shotgun/tui/screens/chat_screen/history/user_question.py +42 -0
  135. shotgun/tui/screens/confirmation_dialog.py +191 -0
  136. shotgun/tui/screens/directory_setup.py +45 -41
  137. shotgun/tui/screens/feedback.py +14 -7
  138. shotgun/tui/screens/github_issue.py +111 -0
  139. shotgun/tui/screens/model_picker.py +77 -32
  140. shotgun/tui/screens/onboarding.py +580 -0
  141. shotgun/tui/screens/pipx_migration.py +205 -0
  142. shotgun/tui/screens/provider_config.py +116 -35
  143. shotgun/tui/screens/shared_specs/__init__.py +21 -0
  144. shotgun/tui/screens/shared_specs/create_spec_dialog.py +273 -0
  145. shotgun/tui/screens/shared_specs/models.py +56 -0
  146. shotgun/tui/screens/shared_specs/share_specs_dialog.py +390 -0
  147. shotgun/tui/screens/shared_specs/upload_progress_screen.py +452 -0
  148. shotgun/tui/screens/shotgun_auth.py +112 -18
  149. shotgun/tui/screens/spec_pull.py +288 -0
  150. shotgun/tui/screens/welcome.py +137 -11
  151. shotgun/tui/services/__init__.py +5 -0
  152. shotgun/tui/services/conversation_service.py +187 -0
  153. shotgun/tui/state/__init__.py +7 -0
  154. shotgun/tui/state/processing_state.py +185 -0
  155. shotgun/tui/utils/mode_progress.py +14 -7
  156. shotgun/tui/widgets/__init__.py +5 -0
  157. shotgun/tui/widgets/widget_coordinator.py +263 -0
  158. shotgun/utils/file_system_utils.py +22 -2
  159. shotgun/utils/marketing.py +110 -0
  160. shotgun/utils/update_checker.py +69 -14
  161. shotgun_sh-0.3.3.dev1.dist-info/METADATA +472 -0
  162. shotgun_sh-0.3.3.dev1.dist-info/RECORD +229 -0
  163. {shotgun_sh-0.2.8.dev2.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/WHEEL +1 -1
  164. {shotgun_sh-0.2.8.dev2.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/entry_points.txt +1 -0
  165. {shotgun_sh-0.2.8.dev2.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/licenses/LICENSE +1 -1
  166. shotgun/tui/screens/chat.py +0 -996
  167. shotgun/tui/screens/chat_screen/history.py +0 -335
  168. shotgun_sh-0.2.8.dev2.dist-info/METADATA +0 -126
  169. shotgun_sh-0.2.8.dev2.dist-info/RECORD +0 -155
  170. /shotgun/agents/{history → conversation/history}/__init__.py +0 -0
  171. /shotgun/agents/{history → conversation/history}/context_extraction.py +0 -0
  172. /shotgun/agents/{history → conversation/history}/history_building.py +0 -0
  173. /shotgun/agents/{history → conversation/history}/message_utils.py +0 -0
  174. /shotgun/agents/{history → conversation/history}/token_counting/__init__.py +0 -0
  175. /shotgun/agents/{history → conversation/history}/token_estimation.py +0 -0
shotgun/agents/common.py CHANGED
@@ -4,6 +4,7 @@ from collections.abc import Callable
4
4
  from pathlib import Path
5
5
  from typing import Any
6
6
 
7
+ import aiofiles
7
8
  from pydantic_ai import (
8
9
  Agent,
9
10
  RunContext,
@@ -24,7 +25,7 @@ from shotgun.utils import ensure_shotgun_directory_exists
24
25
  from shotgun.utils.datetime_utils import get_datetime_context
25
26
  from shotgun.utils.file_system_utils import get_shotgun_base_path
26
27
 
27
- from .history import token_limit_compactor
28
+ from .conversation.history import token_limit_compactor
28
29
  from .messages import AgentSystemPrompt, SystemStatusPrompt
29
30
  from .models import AgentDeps, AgentRuntimeOptions, PipelineConfigEntry
30
31
  from .tools import (
@@ -68,7 +69,7 @@ async def add_system_status_message(
68
69
  existing_files = get_agent_existing_files(deps.agent_mode)
69
70
 
70
71
  # Extract table of contents from the agent's markdown file
71
- markdown_toc = extract_markdown_toc(deps.agent_mode)
72
+ markdown_toc = await extract_markdown_toc(deps.agent_mode)
72
73
 
73
74
  # Get current datetime with timezone information
74
75
  dt_context = get_datetime_context()
@@ -94,7 +95,7 @@ async def add_system_status_message(
94
95
  return message_history
95
96
 
96
97
 
97
- def create_base_agent(
98
+ async def create_base_agent(
98
99
  system_prompt_fn: Callable[[RunContext[AgentDeps]], str],
99
100
  agent_runtime_options: AgentRuntimeOptions,
100
101
  load_codebase_understanding_tools: bool = True,
@@ -119,7 +120,7 @@ def create_base_agent(
119
120
 
120
121
  # Get configured model or fall back to first available provider
121
122
  try:
122
- model_config = get_provider_model(provider)
123
+ model_config = await get_provider_model(provider)
123
124
  provider_name = model_config.provider
124
125
  logger.debug(
125
126
  "🤖 Creating agent with configured %s model: %s",
@@ -194,7 +195,7 @@ def create_base_agent(
194
195
  return agent, deps
195
196
 
196
197
 
197
- def _extract_file_toc_content(
198
+ async def _extract_file_toc_content(
198
199
  file_path: Path, max_depth: int | None = None, max_chars: int = 500
199
200
  ) -> str | None:
200
201
  """Extract TOC from a single file with depth and character limits.
@@ -211,7 +212,8 @@ def _extract_file_toc_content(
211
212
  return None
212
213
 
213
214
  try:
214
- content = file_path.read_text(encoding="utf-8")
215
+ async with aiofiles.open(file_path, encoding="utf-8") as f:
216
+ content = await f.read()
215
217
  lines = content.split("\n")
216
218
 
217
219
  # Extract headings
@@ -257,7 +259,7 @@ def _extract_file_toc_content(
257
259
  return None
258
260
 
259
261
 
260
- def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
262
+ async def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
261
263
  """Extract TOCs from current and prior agents' files in the pipeline.
262
264
 
263
265
  Shows full TOC of agent's own file and high-level summaries of prior agents'
@@ -309,7 +311,9 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
309
311
  for prior_file in config.prior_files:
310
312
  file_path = base_path / prior_file
311
313
  # Only show # and ## headings from prior files, max 500 chars each
312
- prior_toc = _extract_file_toc_content(file_path, max_depth=2, max_chars=500)
314
+ prior_toc = await _extract_file_toc_content(
315
+ file_path, max_depth=2, max_chars=500
316
+ )
313
317
  if prior_toc:
314
318
  # Add section with XML tags
315
319
  toc_sections.append(
@@ -321,7 +325,9 @@ def extract_markdown_toc(agent_mode: AgentType | None) -> str | None:
321
325
  # Extract TOC from own file (full detail)
322
326
  if config.own_file:
323
327
  own_path = base_path / config.own_file
324
- own_toc = _extract_file_toc_content(own_path, max_depth=None, max_chars=2000)
328
+ own_toc = await _extract_file_toc_content(
329
+ own_path, max_depth=None, max_chars=2000
330
+ )
325
331
  if own_toc:
326
332
  # Put own file TOC at the beginning with XML tags
327
333
  toc_sections.insert(
@@ -0,0 +1,89 @@
1
+ # Configuration Management
2
+
3
+ This directory contains the configuration management system for Shotgun, including models, migrations, and provider integration.
4
+
5
+ ## Config Version History
6
+
7
+ ### Version 1 (Config Versioning Introduced)
8
+
9
+ - **Commit**: `f36defc` (Sep 19, 2025)
10
+ - **Title**: "feat: add Sentry error tracking with anonymous user identification"
11
+ - **Key Fields**: `user_id`, `config_version: 1`
12
+ - **Note**: First version to include explicit versioning
13
+
14
+ ### Version 2 (Shotgun Account Provider)
15
+
16
+ - **Commit**: `37a5add` (Oct 3, 2025)
17
+ - **Title**: "feat: add Shotgun Account provider with LiteLLM proxy support"
18
+ - **Key Fields**: `user_id`, `config_version: 2`, added `shotgun` provider config
19
+ - **Note**: Configs without a version field default to v2 during migration
20
+
21
+ ### Version 3 (OAuth Authentication)
22
+
23
+ - **Commit**: `39d2af9` (Oct 6, 2025)
24
+ - **Title**: "feat: implement OAuth-style authentication flow for Shotgun Account"
25
+ - **Key Changes**:
26
+ - Renamed `user_id` → `shotgun_instance_id`
27
+ - Added `supabase_jwt` field to Shotgun Account config
28
+ - **Git Tags**: Both `0.2.11.dev1` and `0.2.11.dev2` are at this version
29
+
30
+ ### Version 4 (Marketing Messages)
31
+
32
+ - **Commit**: `8638a6d` (Nov 4, 2025)
33
+ - **Title**: "feat: add marketing message system for GitHub star promotion"
34
+ - **Key Changes**:
35
+ - Added `marketing` configuration with message tracking
36
+ - Added `shown_welcome_screen` field (set to `False` for existing BYOK users)
37
+
38
+ ### Version 5 (Streaming Detection) - CURRENT
39
+
40
+ - **Commit**: `fded351` (Nov 6, 2025)
41
+ - **Title**: "feat: add config migration for streaming capability field (v4->v5)"
42
+ - **Key Changes**:
43
+ - Added `supports_streaming` field to OpenAI config
44
+ - Added `shown_onboarding_popup` timestamp field
45
+ - Added `supabase_jwt` to Shotgun Account config
46
+
47
+ ## Migration System
48
+
49
+ The migration system is designed to be sequential and idempotent. Migrations are defined in `manager.py`:
50
+
51
+ - `_migrate_v2_to_v3()`: Renames `user_id` to `shotgun_instance_id`
52
+ - `_migrate_v3_to_v4()`: Adds marketing config and welcome screen flag
53
+ - `_migrate_v4_to_v5()`: Adds streaming support fields
54
+
55
+ All migrations preserve user data (API keys, settings) and can be safely run multiple times.
56
+
57
+ ## Adding a New Config Version
58
+
59
+ When adding a new config version:
60
+
61
+ 1. **Update `models.py`**:
62
+ - Increment `CURRENT_CONFIG_VERSION` constant
63
+ - Add new fields to appropriate config models
64
+
65
+ 2. **Create migration function in `manager.py`**:
66
+ ```python
67
+ def _migrate_vN_to_vN+1(data: dict[str, Any]) -> dict[str, Any]:
68
+ """Migrate config from version N to N+1."""
69
+ data["config_version"] = N + 1
70
+ # Add migration logic
71
+ return data
72
+ ```
73
+
74
+ 3. **Register migration**:
75
+ - Add to `migrations` dict in `_apply_migrations()`
76
+
77
+ 4. **Add tests in `test/unit/test_config_migrations.py`**:
78
+ - Create example config for version N
79
+ - Test individual migration function
80
+ - Test sequential migration from version N to current
81
+ - Test with populated configs (non-empty API keys, etc.)
82
+ - Test edge cases
83
+
84
+ ## Files
85
+
86
+ - **`models.py`**: Pydantic models for configuration schema
87
+ - **`manager.py`**: ConfigManager class and migration functions
88
+ - **`provider.py`**: LLM provider integration and model creation
89
+ - **`streaming_test.py`**: OpenAI streaming capability detection
@@ -1,11 +1,20 @@
1
1
  """Configuration module for Shotgun CLI."""
2
2
 
3
- from .manager import ConfigManager, get_config_manager
3
+ from .manager import (
4
+ BACKUP_DIR_NAME,
5
+ ConfigManager,
6
+ ConfigMigrationError,
7
+ get_backup_dir,
8
+ get_config_manager,
9
+ )
4
10
  from .models import ProviderType, ShotgunConfig
5
11
  from .provider import get_provider_model
6
12
 
7
13
  __all__ = [
14
+ "BACKUP_DIR_NAME",
8
15
  "ConfigManager",
16
+ "ConfigMigrationError",
17
+ "get_backup_dir",
9
18
  "get_config_manager",
10
19
  "ProviderType",
11
20
  "ShotgunConfig",
@@ -24,11 +24,5 @@ ANTHROPIC_PROVIDER = ConfigSection.ANTHROPIC.value
24
24
  GOOGLE_PROVIDER = ConfigSection.GOOGLE.value
25
25
  SHOTGUN_PROVIDER = ConfigSection.SHOTGUN.value
26
26
 
27
- # Environment variable names
28
- OPENAI_API_KEY_ENV = "OPENAI_API_KEY"
29
- ANTHROPIC_API_KEY_ENV = "ANTHROPIC_API_KEY"
30
- GEMINI_API_KEY_ENV = "GEMINI_API_KEY"
31
- SHOTGUN_API_KEY_ENV = "SHOTGUN_API_KEY"
32
-
33
27
  # Token limits
34
28
  MEDIUM_TEXT_8K_TOKENS = 8192 # Default max_tokens for web search requests