shotgun-sh 0.2.17__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 (112) hide show
  1. shotgun/agents/agent_manager.py +28 -14
  2. shotgun/agents/common.py +1 -1
  3. shotgun/agents/config/README.md +89 -0
  4. shotgun/agents/config/__init__.py +10 -1
  5. shotgun/agents/config/manager.py +323 -53
  6. shotgun/agents/config/models.py +85 -21
  7. shotgun/agents/config/provider.py +51 -13
  8. shotgun/agents/config/streaming_test.py +119 -0
  9. shotgun/agents/context_analyzer/analyzer.py +6 -2
  10. shotgun/agents/conversation/__init__.py +18 -0
  11. shotgun/agents/conversation/filters.py +164 -0
  12. shotgun/agents/conversation/history/chunking.py +278 -0
  13. shotgun/agents/{history → conversation/history}/compaction.py +27 -1
  14. shotgun/agents/{history → conversation/history}/constants.py +5 -0
  15. shotgun/agents/conversation/history/file_content_deduplication.py +216 -0
  16. shotgun/agents/{history → conversation/history}/history_processors.py +267 -3
  17. shotgun/agents/{history → conversation/history}/token_counting/anthropic.py +8 -0
  18. shotgun/agents/{conversation_manager.py → conversation/manager.py} +1 -1
  19. shotgun/agents/{conversation_history.py → conversation/models.py} +8 -94
  20. shotgun/agents/error/__init__.py +11 -0
  21. shotgun/agents/error/models.py +19 -0
  22. shotgun/agents/runner.py +230 -0
  23. shotgun/agents/tools/web_search/openai.py +1 -1
  24. shotgun/build_constants.py +2 -2
  25. shotgun/cli/clear.py +1 -1
  26. shotgun/cli/compact.py +5 -3
  27. shotgun/cli/context.py +44 -1
  28. shotgun/cli/error_handler.py +24 -0
  29. shotgun/cli/export.py +34 -34
  30. shotgun/cli/plan.py +34 -34
  31. shotgun/cli/research.py +17 -9
  32. shotgun/cli/spec/__init__.py +5 -0
  33. shotgun/cli/spec/backup.py +81 -0
  34. shotgun/cli/spec/commands.py +132 -0
  35. shotgun/cli/spec/models.py +48 -0
  36. shotgun/cli/spec/pull_service.py +219 -0
  37. shotgun/cli/specify.py +20 -19
  38. shotgun/cli/tasks.py +34 -34
  39. shotgun/codebase/core/ingestor.py +153 -7
  40. shotgun/codebase/models.py +2 -0
  41. shotgun/exceptions.py +325 -0
  42. shotgun/llm_proxy/__init__.py +17 -0
  43. shotgun/llm_proxy/client.py +215 -0
  44. shotgun/llm_proxy/models.py +137 -0
  45. shotgun/logging_config.py +42 -0
  46. shotgun/main.py +4 -0
  47. shotgun/posthog_telemetry.py +1 -1
  48. shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +28 -3
  49. shotgun/prompts/agents/partials/interactive_mode.j2 +3 -3
  50. shotgun/prompts/agents/plan.j2 +16 -0
  51. shotgun/prompts/agents/research.j2 +16 -3
  52. shotgun/prompts/agents/specify.j2 +54 -1
  53. shotgun/prompts/agents/state/system_state.j2 +0 -2
  54. shotgun/prompts/agents/tasks.j2 +16 -0
  55. shotgun/prompts/history/chunk_summarization.j2 +34 -0
  56. shotgun/prompts/history/combine_summaries.j2 +53 -0
  57. shotgun/sdk/codebase.py +14 -3
  58. shotgun/settings.py +5 -0
  59. shotgun/shotgun_web/__init__.py +67 -1
  60. shotgun/shotgun_web/client.py +42 -1
  61. shotgun/shotgun_web/constants.py +46 -0
  62. shotgun/shotgun_web/exceptions.py +29 -0
  63. shotgun/shotgun_web/models.py +390 -0
  64. shotgun/shotgun_web/shared_specs/__init__.py +32 -0
  65. shotgun/shotgun_web/shared_specs/file_scanner.py +175 -0
  66. shotgun/shotgun_web/shared_specs/hasher.py +83 -0
  67. shotgun/shotgun_web/shared_specs/models.py +71 -0
  68. shotgun/shotgun_web/shared_specs/upload_pipeline.py +329 -0
  69. shotgun/shotgun_web/shared_specs/utils.py +34 -0
  70. shotgun/shotgun_web/specs_client.py +703 -0
  71. shotgun/shotgun_web/supabase_client.py +31 -0
  72. shotgun/tui/app.py +73 -9
  73. shotgun/tui/containers.py +1 -1
  74. shotgun/tui/layout.py +5 -0
  75. shotgun/tui/screens/chat/chat_screen.py +372 -95
  76. shotgun/tui/screens/chat/codebase_index_prompt_screen.py +196 -17
  77. shotgun/tui/screens/chat_screen/command_providers.py +13 -2
  78. shotgun/tui/screens/chat_screen/hint_message.py +76 -1
  79. shotgun/tui/screens/confirmation_dialog.py +40 -0
  80. shotgun/tui/screens/directory_setup.py +45 -41
  81. shotgun/tui/screens/feedback.py +10 -3
  82. shotgun/tui/screens/github_issue.py +11 -2
  83. shotgun/tui/screens/model_picker.py +28 -8
  84. shotgun/tui/screens/onboarding.py +149 -0
  85. shotgun/tui/screens/pipx_migration.py +58 -6
  86. shotgun/tui/screens/provider_config.py +66 -8
  87. shotgun/tui/screens/shared_specs/__init__.py +21 -0
  88. shotgun/tui/screens/shared_specs/create_spec_dialog.py +273 -0
  89. shotgun/tui/screens/shared_specs/models.py +56 -0
  90. shotgun/tui/screens/shared_specs/share_specs_dialog.py +390 -0
  91. shotgun/tui/screens/shared_specs/upload_progress_screen.py +452 -0
  92. shotgun/tui/screens/shotgun_auth.py +110 -16
  93. shotgun/tui/screens/spec_pull.py +288 -0
  94. shotgun/tui/screens/welcome.py +123 -0
  95. shotgun/tui/services/conversation_service.py +5 -2
  96. shotgun/tui/widgets/widget_coordinator.py +1 -1
  97. {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/METADATA +9 -2
  98. {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/RECORD +112 -77
  99. {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/WHEEL +1 -1
  100. /shotgun/agents/{history → conversation/history}/__init__.py +0 -0
  101. /shotgun/agents/{history → conversation/history}/context_extraction.py +0 -0
  102. /shotgun/agents/{history → conversation/history}/history_building.py +0 -0
  103. /shotgun/agents/{history → conversation/history}/message_utils.py +0 -0
  104. /shotgun/agents/{history → conversation/history}/token_counting/__init__.py +0 -0
  105. /shotgun/agents/{history → conversation/history}/token_counting/base.py +0 -0
  106. /shotgun/agents/{history → conversation/history}/token_counting/openai.py +0 -0
  107. /shotgun/agents/{history → conversation/history}/token_counting/sentencepiece_counter.py +0 -0
  108. /shotgun/agents/{history → conversation/history}/token_counting/tokenizer_cache.py +0 -0
  109. /shotgun/agents/{history → conversation/history}/token_counting/utils.py +0 -0
  110. /shotgun/agents/{history → conversation/history}/token_estimation.py +0 -0
  111. {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/entry_points.txt +0 -0
  112. {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/licenses/LICENSE +0 -0
@@ -17,7 +17,7 @@ from tenacity import (
17
17
  )
18
18
 
19
19
  if TYPE_CHECKING:
20
- from shotgun.agents.conversation_history import ConversationState
20
+ from shotgun.agents.conversation import ConversationState
21
21
 
22
22
  from pydantic_ai import (
23
23
  Agent,
@@ -68,8 +68,8 @@ from shotgun.posthog_telemetry import track_event
68
68
  from shotgun.tui.screens.chat_screen.hint_message import HintMessage
69
69
  from shotgun.utils.source_detection import detect_source
70
70
 
71
+ from .conversation.history.compaction import apply_persistent_compaction
71
72
  from .export import create_export_agent
72
- from .history.compaction import apply_persistent_compaction
73
73
  from .messages import AgentSystemPrompt
74
74
  from .models import AgentDeps, AgentRuntimeOptions
75
75
  from .plan import create_plan_agent
@@ -615,19 +615,33 @@ class AgentManager(Widget):
615
615
  self._stream_state = _PartialStreamState()
616
616
 
617
617
  model_name = ""
618
+ supports_streaming = True # Default to streaming enabled
619
+
618
620
  if hasattr(deps, "llm_model") and deps.llm_model is not None:
619
621
  model_name = deps.llm_model.name
622
+ supports_streaming = deps.llm_model.supports_streaming
620
623
 
621
- # Check if it's a Shotgun account
622
- is_shotgun_account = (
623
- hasattr(deps, "llm_model")
624
- and deps.llm_model is not None
625
- and deps.llm_model.key_provider == KeyProvider.SHOTGUN
626
- )
627
-
628
- # Only disable streaming for GPT-5 if NOT a Shotgun account
629
- # Shotgun accounts support streaming for GPT-5
630
- is_gpt5_byok = "gpt-5" in model_name.lower() and not is_shotgun_account
624
+ # Add hint message if streaming is disabled for BYOK GPT-5 models
625
+ if (
626
+ not supports_streaming
627
+ and deps.llm_model.key_provider == KeyProvider.BYOK
628
+ ):
629
+ self.ui_message_history.append(
630
+ HintMessage(
631
+ message=(
632
+ "⚠️ **Streaming not available for GPT-5**\n\n"
633
+ "Your OpenAI organization doesn't have streaming enabled for this model.\n\n"
634
+ "**Options:**\n"
635
+ "- Get a [Shotgun Account](https://shotgun.sh) - streaming works out of the box\n"
636
+ "- Complete [Biometric Verification](https://platform.openai.com/settings/organization/general) with OpenAI, then:\n"
637
+ " 1. Press `Ctrl+P` → Open Provider Setup\n"
638
+ " 2. Select OpenAI → Clear key\n"
639
+ " 3. Re-add your OpenAI API key\n\n"
640
+ "Continuing without streaming (responses will appear all at once)."
641
+ )
642
+ )
643
+ )
644
+ self._post_messages_updated()
631
645
 
632
646
  # Track message send event
633
647
  event_name = f"message_send_{self._current_agent_type.value}"
@@ -647,7 +661,7 @@ class AgentManager(Widget):
647
661
  usage_limits=usage_limits,
648
662
  message_history=message_history,
649
663
  event_stream_handler=self._handle_event_stream
650
- if not is_gpt5_byok
664
+ if supports_streaming
651
665
  else None,
652
666
  **kwargs,
653
667
  )
@@ -1300,7 +1314,7 @@ class AgentManager(Widget):
1300
1314
  Returns:
1301
1315
  ConversationState object containing UI and agent messages and current type
1302
1316
  """
1303
- from shotgun.agents.conversation_history import ConversationState
1317
+ from shotgun.agents.conversation import ConversationState
1304
1318
 
1305
1319
  return ConversationState(
1306
1320
  agent_messages=self.message_history.copy(),
shotgun/agents/common.py CHANGED
@@ -25,7 +25,7 @@ from shotgun.utils import ensure_shotgun_directory_exists
25
25
  from shotgun.utils.datetime_utils import get_datetime_context
26
26
  from shotgun.utils.file_system_utils import get_shotgun_base_path
27
27
 
28
- from .history import token_limit_compactor
28
+ from .conversation.history import token_limit_compactor
29
29
  from .messages import AgentSystemPrompt, SystemStatusPrompt
30
30
  from .models import AgentDeps, AgentRuntimeOptions, PipelineConfigEntry
31
31
  from .tools import (
@@ -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",