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.
- shotgun/agents/agent_manager.py +28 -14
- shotgun/agents/common.py +1 -1
- shotgun/agents/config/README.md +89 -0
- shotgun/agents/config/__init__.py +10 -1
- shotgun/agents/config/manager.py +323 -53
- shotgun/agents/config/models.py +85 -21
- shotgun/agents/config/provider.py +51 -13
- shotgun/agents/config/streaming_test.py +119 -0
- shotgun/agents/context_analyzer/analyzer.py +6 -2
- shotgun/agents/conversation/__init__.py +18 -0
- shotgun/agents/conversation/filters.py +164 -0
- shotgun/agents/conversation/history/chunking.py +278 -0
- shotgun/agents/{history → conversation/history}/compaction.py +27 -1
- shotgun/agents/{history → conversation/history}/constants.py +5 -0
- shotgun/agents/conversation/history/file_content_deduplication.py +216 -0
- shotgun/agents/{history → conversation/history}/history_processors.py +267 -3
- shotgun/agents/{history → conversation/history}/token_counting/anthropic.py +8 -0
- shotgun/agents/{conversation_manager.py → conversation/manager.py} +1 -1
- shotgun/agents/{conversation_history.py → conversation/models.py} +8 -94
- shotgun/agents/error/__init__.py +11 -0
- shotgun/agents/error/models.py +19 -0
- shotgun/agents/runner.py +230 -0
- shotgun/agents/tools/web_search/openai.py +1 -1
- shotgun/build_constants.py +2 -2
- shotgun/cli/clear.py +1 -1
- shotgun/cli/compact.py +5 -3
- shotgun/cli/context.py +44 -1
- shotgun/cli/error_handler.py +24 -0
- shotgun/cli/export.py +34 -34
- shotgun/cli/plan.py +34 -34
- shotgun/cli/research.py +17 -9
- shotgun/cli/spec/__init__.py +5 -0
- shotgun/cli/spec/backup.py +81 -0
- shotgun/cli/spec/commands.py +132 -0
- shotgun/cli/spec/models.py +48 -0
- shotgun/cli/spec/pull_service.py +219 -0
- shotgun/cli/specify.py +20 -19
- shotgun/cli/tasks.py +34 -34
- shotgun/codebase/core/ingestor.py +153 -7
- shotgun/codebase/models.py +2 -0
- shotgun/exceptions.py +325 -0
- shotgun/llm_proxy/__init__.py +17 -0
- shotgun/llm_proxy/client.py +215 -0
- shotgun/llm_proxy/models.py +137 -0
- shotgun/logging_config.py +42 -0
- shotgun/main.py +4 -0
- shotgun/posthog_telemetry.py +1 -1
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +28 -3
- shotgun/prompts/agents/partials/interactive_mode.j2 +3 -3
- shotgun/prompts/agents/plan.j2 +16 -0
- shotgun/prompts/agents/research.j2 +16 -3
- shotgun/prompts/agents/specify.j2 +54 -1
- shotgun/prompts/agents/state/system_state.j2 +0 -2
- shotgun/prompts/agents/tasks.j2 +16 -0
- shotgun/prompts/history/chunk_summarization.j2 +34 -0
- shotgun/prompts/history/combine_summaries.j2 +53 -0
- shotgun/sdk/codebase.py +14 -3
- shotgun/settings.py +5 -0
- shotgun/shotgun_web/__init__.py +67 -1
- shotgun/shotgun_web/client.py +42 -1
- shotgun/shotgun_web/constants.py +46 -0
- shotgun/shotgun_web/exceptions.py +29 -0
- shotgun/shotgun_web/models.py +390 -0
- shotgun/shotgun_web/shared_specs/__init__.py +32 -0
- shotgun/shotgun_web/shared_specs/file_scanner.py +175 -0
- shotgun/shotgun_web/shared_specs/hasher.py +83 -0
- shotgun/shotgun_web/shared_specs/models.py +71 -0
- shotgun/shotgun_web/shared_specs/upload_pipeline.py +329 -0
- shotgun/shotgun_web/shared_specs/utils.py +34 -0
- shotgun/shotgun_web/specs_client.py +703 -0
- shotgun/shotgun_web/supabase_client.py +31 -0
- shotgun/tui/app.py +73 -9
- shotgun/tui/containers.py +1 -1
- shotgun/tui/layout.py +5 -0
- shotgun/tui/screens/chat/chat_screen.py +372 -95
- shotgun/tui/screens/chat/codebase_index_prompt_screen.py +196 -17
- shotgun/tui/screens/chat_screen/command_providers.py +13 -2
- shotgun/tui/screens/chat_screen/hint_message.py +76 -1
- shotgun/tui/screens/confirmation_dialog.py +40 -0
- shotgun/tui/screens/directory_setup.py +45 -41
- shotgun/tui/screens/feedback.py +10 -3
- shotgun/tui/screens/github_issue.py +11 -2
- shotgun/tui/screens/model_picker.py +28 -8
- shotgun/tui/screens/onboarding.py +149 -0
- shotgun/tui/screens/pipx_migration.py +58 -6
- shotgun/tui/screens/provider_config.py +66 -8
- shotgun/tui/screens/shared_specs/__init__.py +21 -0
- shotgun/tui/screens/shared_specs/create_spec_dialog.py +273 -0
- shotgun/tui/screens/shared_specs/models.py +56 -0
- shotgun/tui/screens/shared_specs/share_specs_dialog.py +390 -0
- shotgun/tui/screens/shared_specs/upload_progress_screen.py +452 -0
- shotgun/tui/screens/shotgun_auth.py +110 -16
- shotgun/tui/screens/spec_pull.py +288 -0
- shotgun/tui/screens/welcome.py +123 -0
- shotgun/tui/services/conversation_service.py +5 -2
- shotgun/tui/widgets/widget_coordinator.py +1 -1
- {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/METADATA +9 -2
- {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/RECORD +112 -77
- {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/WHEEL +1 -1
- /shotgun/agents/{history → conversation/history}/__init__.py +0 -0
- /shotgun/agents/{history → conversation/history}/context_extraction.py +0 -0
- /shotgun/agents/{history → conversation/history}/history_building.py +0 -0
- /shotgun/agents/{history → conversation/history}/message_utils.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/__init__.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/base.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/openai.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/sentencepiece_counter.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/tokenizer_cache.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_counting/utils.py +0 -0
- /shotgun/agents/{history → conversation/history}/token_estimation.py +0 -0
- {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/entry_points.txt +0 -0
- {shotgun_sh-0.2.17.dist-info → shotgun_sh-0.3.3.dev1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Supabase Storage download utilities."""
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from shotgun.logging_config import get_logger
|
|
6
|
+
|
|
7
|
+
logger = get_logger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def download_file_from_url(download_url: str) -> bytes:
|
|
11
|
+
"""Download a file from a presigned Supabase Storage URL.
|
|
12
|
+
|
|
13
|
+
The API returns presigned URLs with embedded tokens that don't require
|
|
14
|
+
any authentication headers.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
download_url: Presigned Supabase Storage URL
|
|
18
|
+
(e.g., "https://...supabase.co/storage/v1/object/sign/...?token=...")
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
File contents as bytes
|
|
22
|
+
|
|
23
|
+
Raises:
|
|
24
|
+
httpx.HTTPStatusError: If download fails
|
|
25
|
+
"""
|
|
26
|
+
logger.debug("Downloading file from: %s", download_url)
|
|
27
|
+
|
|
28
|
+
async with httpx.AsyncClient(timeout=60.0) as client:
|
|
29
|
+
response = await client.get(download_url)
|
|
30
|
+
response.raise_for_status()
|
|
31
|
+
return response.content
|
shotgun/tui/app.py
CHANGED
|
@@ -6,12 +6,18 @@ from textual.binding import Binding
|
|
|
6
6
|
from textual.screen import Screen
|
|
7
7
|
|
|
8
8
|
from shotgun.agents.agent_manager import AgentManager
|
|
9
|
-
from shotgun.agents.config import
|
|
9
|
+
from shotgun.agents.config import (
|
|
10
|
+
ConfigManager,
|
|
11
|
+
get_config_manager,
|
|
12
|
+
)
|
|
10
13
|
from shotgun.agents.models import AgentType
|
|
11
14
|
from shotgun.logging_config import get_logger
|
|
12
15
|
from shotgun.tui.containers import TUIContainer
|
|
13
16
|
from shotgun.tui.screens.splash import SplashScreen
|
|
14
|
-
from shotgun.utils.file_system_utils import
|
|
17
|
+
from shotgun.utils.file_system_utils import (
|
|
18
|
+
ensure_shotgun_directory_exists,
|
|
19
|
+
get_shotgun_base_path,
|
|
20
|
+
)
|
|
15
21
|
from shotgun.utils.update_checker import (
|
|
16
22
|
detect_installation_method,
|
|
17
23
|
perform_auto_update_async,
|
|
@@ -31,10 +37,10 @@ logger = get_logger(__name__)
|
|
|
31
37
|
class ShotgunApp(App[None]):
|
|
32
38
|
# ChatScreen removed from SCREENS dict since it requires dependency injection
|
|
33
39
|
# and is instantiated manually in refresh_startup_screen()
|
|
40
|
+
# DirectorySetupScreen also removed since it requires error_message parameter
|
|
34
41
|
SCREENS = {
|
|
35
42
|
"provider_config": ProviderConfigScreen,
|
|
36
43
|
"model_picker": ModelPickerScreen,
|
|
37
|
-
"directory_setup": DirectorySetupScreen,
|
|
38
44
|
"github_issue": GitHubIssueScreen,
|
|
39
45
|
}
|
|
40
46
|
BINDINGS = [
|
|
@@ -48,12 +54,16 @@ class ShotgunApp(App[None]):
|
|
|
48
54
|
no_update_check: bool = False,
|
|
49
55
|
continue_session: bool = False,
|
|
50
56
|
force_reindex: bool = False,
|
|
57
|
+
show_pull_hint: bool = False,
|
|
58
|
+
pull_version_id: str | None = None,
|
|
51
59
|
) -> None:
|
|
52
60
|
super().__init__()
|
|
53
61
|
self.config_manager: ConfigManager = get_config_manager()
|
|
54
62
|
self.no_update_check = no_update_check
|
|
55
63
|
self.continue_session = continue_session
|
|
56
64
|
self.force_reindex = force_reindex
|
|
65
|
+
self.show_pull_hint = show_pull_hint
|
|
66
|
+
self.pull_version_id = pull_version_id
|
|
57
67
|
|
|
58
68
|
# Initialize dependency injection container
|
|
59
69
|
self.container = TUIContainer()
|
|
@@ -71,6 +81,8 @@ class ShotgunApp(App[None]):
|
|
|
71
81
|
"tui_started",
|
|
72
82
|
{
|
|
73
83
|
"installation_method": detect_installation_method(),
|
|
84
|
+
"terminal_width": self.size.width,
|
|
85
|
+
"terminal_height": self.size.height,
|
|
74
86
|
},
|
|
75
87
|
)
|
|
76
88
|
|
|
@@ -99,7 +111,10 @@ class ShotgunApp(App[None]):
|
|
|
99
111
|
# Run async config loading in worker
|
|
100
112
|
async def _check_config() -> None:
|
|
101
113
|
# Show welcome screen if no providers are configured OR if user hasn't seen it yet
|
|
114
|
+
# Note: If config migration fails, ConfigManager will auto-create fresh config
|
|
115
|
+
# and set migration_failed flag, which WelcomeScreen will display
|
|
102
116
|
config = await self.config_manager.load()
|
|
117
|
+
|
|
103
118
|
has_any_key = await self.config_manager.has_any_provider_key()
|
|
104
119
|
if not has_any_key or not config.shown_welcome_screen:
|
|
105
120
|
if isinstance(self.screen, WelcomeScreen):
|
|
@@ -111,17 +126,43 @@ class ShotgunApp(App[None]):
|
|
|
111
126
|
)
|
|
112
127
|
return
|
|
113
128
|
|
|
129
|
+
# Try to create .shotgun directory if it doesn't exist
|
|
114
130
|
if not self.check_local_shotgun_directory_exists():
|
|
115
|
-
|
|
131
|
+
try:
|
|
132
|
+
path = ensure_shotgun_directory_exists()
|
|
133
|
+
# Verify directory was created successfully
|
|
134
|
+
if not path.is_dir():
|
|
135
|
+
# Show error screen if creation failed
|
|
136
|
+
if isinstance(self.screen, DirectorySetupScreen):
|
|
137
|
+
return
|
|
138
|
+
self.push_screen(
|
|
139
|
+
DirectorySetupScreen(
|
|
140
|
+
error_message="Unable to create .shotgun directory due to filesystem conflict."
|
|
141
|
+
),
|
|
142
|
+
callback=lambda _arg: self.refresh_startup_screen(),
|
|
143
|
+
)
|
|
144
|
+
return
|
|
145
|
+
except Exception as exc:
|
|
146
|
+
# Show error screen if creation failed with exception
|
|
147
|
+
if isinstance(self.screen, DirectorySetupScreen):
|
|
148
|
+
return
|
|
149
|
+
self.push_screen(
|
|
150
|
+
DirectorySetupScreen(error_message=str(exc)),
|
|
151
|
+
callback=lambda _arg: self.refresh_startup_screen(),
|
|
152
|
+
)
|
|
116
153
|
return
|
|
117
154
|
|
|
118
|
-
|
|
119
|
-
DirectorySetupScreen(),
|
|
120
|
-
callback=lambda _arg: self.refresh_startup_screen(),
|
|
121
|
-
)
|
|
155
|
+
if isinstance(self.screen, ChatScreen):
|
|
122
156
|
return
|
|
123
157
|
|
|
124
|
-
|
|
158
|
+
# If we have a version to pull, show pull screen first
|
|
159
|
+
if self.pull_version_id:
|
|
160
|
+
from .screens.spec_pull import SpecPullScreen
|
|
161
|
+
|
|
162
|
+
self.push_screen(
|
|
163
|
+
SpecPullScreen(self.pull_version_id),
|
|
164
|
+
callback=self._handle_pull_complete,
|
|
165
|
+
)
|
|
125
166
|
return
|
|
126
167
|
|
|
127
168
|
# Create ChatScreen with all dependencies injected from container
|
|
@@ -155,6 +196,7 @@ class ShotgunApp(App[None]):
|
|
|
155
196
|
deps=agent_deps,
|
|
156
197
|
continue_session=self.continue_session,
|
|
157
198
|
force_reindex=self.force_reindex,
|
|
199
|
+
show_pull_hint=self.show_pull_hint,
|
|
158
200
|
)
|
|
159
201
|
|
|
160
202
|
# Update the ProcessingStateManager and WidgetCoordinator with the actual ChatScreen instance
|
|
@@ -170,6 +212,22 @@ class ShotgunApp(App[None]):
|
|
|
170
212
|
shotgun_dir = get_shotgun_base_path()
|
|
171
213
|
return shotgun_dir.exists() and shotgun_dir.is_dir()
|
|
172
214
|
|
|
215
|
+
def _handle_pull_complete(self, success: bool | None) -> None:
|
|
216
|
+
"""Handle completion of spec pull screen.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
success: Whether the pull was successful, or None if dismissed.
|
|
220
|
+
"""
|
|
221
|
+
# Clear version_id so we don't pull again on next refresh
|
|
222
|
+
self.pull_version_id = None
|
|
223
|
+
|
|
224
|
+
if success:
|
|
225
|
+
# Enable hint for ChatScreen
|
|
226
|
+
self.show_pull_hint = True
|
|
227
|
+
|
|
228
|
+
# Continue to ChatScreen
|
|
229
|
+
self.refresh_startup_screen()
|
|
230
|
+
|
|
173
231
|
async def action_quit(self) -> None:
|
|
174
232
|
"""Quit the application."""
|
|
175
233
|
# Shut down PostHog client to prevent threading errors
|
|
@@ -196,6 +254,8 @@ def run(
|
|
|
196
254
|
no_update_check: bool = False,
|
|
197
255
|
continue_session: bool = False,
|
|
198
256
|
force_reindex: bool = False,
|
|
257
|
+
show_pull_hint: bool = False,
|
|
258
|
+
pull_version_id: str | None = None,
|
|
199
259
|
) -> None:
|
|
200
260
|
"""Run the TUI application.
|
|
201
261
|
|
|
@@ -203,6 +263,8 @@ def run(
|
|
|
203
263
|
no_update_check: If True, disable automatic update checks.
|
|
204
264
|
continue_session: If True, continue from previous conversation.
|
|
205
265
|
force_reindex: If True, force re-indexing of codebase (ignores existing index).
|
|
266
|
+
show_pull_hint: If True, show hint about recently pulled spec.
|
|
267
|
+
pull_version_id: If provided, pull this spec version before showing ChatScreen.
|
|
206
268
|
"""
|
|
207
269
|
# Clean up any corrupted databases BEFORE starting the TUI
|
|
208
270
|
# This prevents crashes from corrupted databases during initialization
|
|
@@ -228,6 +290,8 @@ def run(
|
|
|
228
290
|
no_update_check=no_update_check,
|
|
229
291
|
continue_session=continue_session,
|
|
230
292
|
force_reindex=force_reindex,
|
|
293
|
+
show_pull_hint=show_pull_hint,
|
|
294
|
+
pull_version_id=pull_version_id,
|
|
231
295
|
)
|
|
232
296
|
app.run(inline_no_clear=True)
|
|
233
297
|
|
shotgun/tui/containers.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
from dependency_injector import containers, providers
|
|
6
6
|
from pydantic_ai import RunContext
|
|
7
7
|
|
|
8
|
-
from shotgun.agents.
|
|
8
|
+
from shotgun.agents.conversation import ConversationManager
|
|
9
9
|
from shotgun.agents.models import AgentDeps
|
|
10
10
|
from shotgun.sdk.codebase import CodebaseSDK
|
|
11
11
|
from shotgun.tui.commands import CommandHandler
|
shotgun/tui/layout.py
ADDED