shotgun-sh 0.2.7.dev2__py3-none-any.whl → 0.2.8.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.

Potentially problematic release.


This version of shotgun-sh might be problematic. Click here for more details.

shotgun/main.py CHANGED
@@ -125,6 +125,34 @@ def main(
125
125
  help="Continue previous TUI conversation",
126
126
  ),
127
127
  ] = False,
128
+ web: Annotated[
129
+ bool,
130
+ typer.Option(
131
+ "--web",
132
+ help="Serve TUI as web application",
133
+ ),
134
+ ] = False,
135
+ port: Annotated[
136
+ int,
137
+ typer.Option(
138
+ "--port",
139
+ help="Port for web server (only used with --web)",
140
+ ),
141
+ ] = 8000,
142
+ host: Annotated[
143
+ str,
144
+ typer.Option(
145
+ "--host",
146
+ help="Host address for web server (only used with --web)",
147
+ ),
148
+ ] = "localhost",
149
+ public_url: Annotated[
150
+ str | None,
151
+ typer.Option(
152
+ "--public-url",
153
+ help="Public URL if behind proxy (only used with --web)",
154
+ ),
155
+ ] = None,
128
156
  ) -> None:
129
157
  """Shotgun - AI-powered CLI tool."""
130
158
  logger.debug("Starting shotgun CLI application")
@@ -134,16 +162,32 @@ def main(
134
162
  perform_auto_update_async(no_update_check=no_update_check)
135
163
 
136
164
  if ctx.invoked_subcommand is None and not ctx.resilient_parsing:
137
- logger.debug("Launching shotgun TUI application")
138
- try:
139
- tui_app.run(
140
- no_update_check=no_update_check, continue_session=continue_session
141
- )
142
- finally:
143
- # Ensure PostHog is shut down cleanly even if TUI exits unexpectedly
144
- from shotgun.posthog_telemetry import shutdown
145
-
146
- shutdown()
165
+ if web:
166
+ logger.debug("Launching shotgun TUI as web application")
167
+ try:
168
+ tui_app.serve(
169
+ host=host,
170
+ port=port,
171
+ public_url=public_url,
172
+ no_update_check=no_update_check,
173
+ continue_session=continue_session,
174
+ )
175
+ finally:
176
+ # Ensure PostHog is shut down cleanly even if server exits unexpectedly
177
+ from shotgun.posthog_telemetry import shutdown
178
+
179
+ shutdown()
180
+ else:
181
+ logger.debug("Launching shotgun TUI application")
182
+ try:
183
+ tui_app.run(
184
+ no_update_check=no_update_check, continue_session=continue_session
185
+ )
186
+ finally:
187
+ # Ensure PostHog is shut down cleanly even if TUI exits unexpectedly
188
+ from shotgun.posthog_telemetry import shutdown
189
+
190
+ shutdown()
147
191
  raise typer.Exit()
148
192
 
149
193
  # For CLI commands, register PostHog shutdown handler
shotgun/tui/app.py CHANGED
@@ -152,5 +152,121 @@ def run(no_update_check: bool = False, continue_session: bool = False) -> None:
152
152
  app.run(inline_no_clear=True)
153
153
 
154
154
 
155
+ def serve(
156
+ host: str = "localhost",
157
+ port: int = 8000,
158
+ public_url: str | None = None,
159
+ no_update_check: bool = False,
160
+ continue_session: bool = False,
161
+ ) -> None:
162
+ """Serve the TUI application as a web application.
163
+
164
+ Args:
165
+ host: Host address for the web server.
166
+ port: Port number for the web server.
167
+ public_url: Public URL if behind a proxy.
168
+ no_update_check: If True, disable automatic update checks.
169
+ continue_session: If True, continue from previous conversation.
170
+ """
171
+ # Clean up any corrupted databases BEFORE starting the TUI
172
+ # This prevents crashes from corrupted databases during initialization
173
+ import asyncio
174
+
175
+ from textual_serve.server import Server
176
+
177
+ from shotgun.codebase.core.manager import CodebaseGraphManager
178
+ from shotgun.utils import get_shotgun_home
179
+
180
+ storage_dir = get_shotgun_home() / "codebases"
181
+ manager = CodebaseGraphManager(storage_dir)
182
+
183
+ try:
184
+ removed = asyncio.run(manager.cleanup_corrupted_databases())
185
+ if removed:
186
+ logger.info(
187
+ f"Cleaned up {len(removed)} corrupted database(s) before TUI startup"
188
+ )
189
+ except Exception as e:
190
+ logger.error(f"Failed to cleanup corrupted databases: {e}")
191
+ # Continue anyway - the TUI can still function
192
+
193
+ # Create a new event loop after asyncio.run() closes the previous one
194
+ # This is needed for the Server.serve() method
195
+ loop = asyncio.new_event_loop()
196
+ asyncio.set_event_loop(loop)
197
+
198
+ # Build the command string based on flags
199
+ command = "shotgun"
200
+ if no_update_check:
201
+ command += " --no-update-check"
202
+ if continue_session:
203
+ command += " --continue"
204
+
205
+ # Create and start the server with hardcoded title and debug=False
206
+ server = Server(
207
+ command=command,
208
+ host=host,
209
+ port=port,
210
+ title="The Shotgun",
211
+ public_url=public_url,
212
+ )
213
+
214
+ # Set up graceful shutdown on SIGTERM/SIGINT
215
+ import signal
216
+ import sys
217
+
218
+ def signal_handler(_signum: int, _frame: Any) -> None:
219
+ """Handle shutdown signals gracefully."""
220
+ from shotgun.posthog_telemetry import shutdown
221
+
222
+ logger.info("Received shutdown signal, cleaning up...")
223
+ # Restore stdout/stderr before shutting down
224
+ sys.stdout = original_stdout
225
+ sys.stderr = original_stderr
226
+ shutdown()
227
+ sys.exit(0)
228
+
229
+ signal.signal(signal.SIGTERM, signal_handler)
230
+ signal.signal(signal.SIGINT, signal_handler)
231
+
232
+ # Suppress the textual-serve banner by redirecting stdout/stderr
233
+ import io
234
+
235
+ # Capture and suppress the banner, but show the actual serving URL
236
+ original_stdout = sys.stdout
237
+ original_stderr = sys.stderr
238
+
239
+ captured_output = io.StringIO()
240
+ sys.stdout = captured_output
241
+ sys.stderr = captured_output
242
+
243
+ try:
244
+ # This will print the banner to our captured output
245
+ import logging
246
+
247
+ # Temporarily set logging to ERROR level to suppress INFO messages
248
+ textual_serve_logger = logging.getLogger("textual_serve")
249
+ original_level = textual_serve_logger.level
250
+ textual_serve_logger.setLevel(logging.ERROR)
251
+
252
+ # Print our own message to the original stdout
253
+ sys.stdout = original_stdout
254
+ sys.stderr = original_stderr
255
+ print(f"Serving Shotgun TUI at http://{host}:{port}")
256
+ print("Press Ctrl+C to quit")
257
+
258
+ # Now suppress output again for the serve call
259
+ sys.stdout = captured_output
260
+ sys.stderr = captured_output
261
+
262
+ server.serve(debug=False)
263
+ finally:
264
+ # Restore original stdout/stderr
265
+ sys.stdout = original_stdout
266
+ sys.stderr = original_stderr
267
+ if "textual_serve_logger" in locals():
268
+ textual_serve_logger.setLevel(original_level)
269
+
270
+
155
271
  if __name__ == "__main__":
156
272
  run()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shotgun-sh
3
- Version: 0.2.7.dev2
3
+ Version: 0.2.8.dev1
4
4
  Summary: AI-powered research, planning, and task management CLI tool
5
5
  Project-URL: Homepage, https://shotgun.sh/
6
6
  Project-URL: Repository, https://github.com/shotgun-sh/shotgun
@@ -36,6 +36,7 @@ Requires-Dist: sentencepiece>=0.2.0
36
36
  Requires-Dist: sentry-sdk[pure-eval]>=2.0.0
37
37
  Requires-Dist: tenacity>=8.0.0
38
38
  Requires-Dist: textual-dev>=1.7.0
39
+ Requires-Dist: textual-serve>=0.1.0
39
40
  Requires-Dist: textual>=6.1.0
40
41
  Requires-Dist: tiktoken>=0.7.0
41
42
  Requires-Dist: tree-sitter-go>=0.23.0
@@ -2,7 +2,7 @@ shotgun/__init__.py,sha256=P40K0fnIsb7SKcQrFnXZ4aREjpWchVDhvM1HxI4cyIQ,104
2
2
  shotgun/api_endpoints.py,sha256=TvxuJyMrZLy6KZTrR6lrdkG8OBtb3TJ48qaw3pWitO0,526
3
3
  shotgun/build_constants.py,sha256=RXNxMz46HaB5jucgMVpw8a2yCJqjbhTOh0PddyEVMN8,713
4
4
  shotgun/logging_config.py,sha256=UKenihvgH8OA3W0b8ZFcItYaFJVe9MlsMYlcevyW1HY,7440
5
- shotgun/main.py,sha256=RA3q1xPfqxCu43UmgI2ryZpA-IxPhJb_MJrbLqp9c_g,5140
5
+ shotgun/main.py,sha256=8t-jw4KZAlvUVvoqMlp0rTVCXtJx4herSheI2N8i-8Y,6445
6
6
  shotgun/posthog_telemetry.py,sha256=TOiyBtLg21SttHGWKc4-e-PQgpbq6Uz_4OzlvlxMcZ0,6099
7
7
  shotgun/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  shotgun/sentry_telemetry.py,sha256=VD8es-tREfgtRKhDsEVvqpo0_kM_ab6iVm2lkOEmTlI,2950
@@ -119,7 +119,7 @@ shotgun/shotgun_web/client.py,sha256=n5DDuVfSa6VPZjhSsfSxQlSFOnhgDHyidRnB8Hv9XF4
119
119
  shotgun/shotgun_web/constants.py,sha256=eNvtjlu81bAVQaCwZXOVjSpDopUm9pf34XuZEvuMiko,661
120
120
  shotgun/shotgun_web/models.py,sha256=Ie9VfqKZM2tIJhIjentU9qLoNaMZvnUJaIu-xg9kQsA,1391
121
121
  shotgun/tui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
- shotgun/tui/app.py,sha256=B2tKbXeGhWBIVec1jJHGAuBcP1SMbO_6xol2OaBpw2Y,5374
122
+ shotgun/tui/app.py,sha256=dBoniec5iscVozM7BTDiKAwMWLUvzw2CioLiTqtmoqo,9184
123
123
  shotgun/tui/filtered_codebase_service.py,sha256=lJ8gTMhIveTatmvmGLP299msWWTkVYKwvY_2FhuL2s4,1687
124
124
  shotgun/tui/styles.tcss,sha256=ETyyw1bpMBOqTi5RLcAJUScdPWTvAWEqE9YcT0kVs_E,121
125
125
  shotgun/tui/commands/__init__.py,sha256=8D5lvtpqMW5-fF7Bg3oJtUzU75cKOv6aUaHYYszydU8,2518
@@ -148,8 +148,8 @@ shotgun/utils/env_utils.py,sha256=ulM3BRi9ZhS7uC-zorGeDQm4SHvsyFuuU9BtVPqdrHY,14
148
148
  shotgun/utils/file_system_utils.py,sha256=l-0p1bEHF34OU19MahnRFdClHufThfGAjQ431teAIp0,1004
149
149
  shotgun/utils/source_detection.py,sha256=Co6Q03R3fT771TF3RzB-70stfjNP2S4F_ArZKibwzm8,454
150
150
  shotgun/utils/update_checker.py,sha256=IgzPHRhS1ETH7PnJR_dIx6lxgr1qHpCkMTgzUxvGjhI,7586
151
- shotgun_sh-0.2.7.dev2.dist-info/METADATA,sha256=Y5ppF2C65mLBLz-vWbdXP7wQuecONMesrSeIKkjrXd4,4299
152
- shotgun_sh-0.2.7.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
153
- shotgun_sh-0.2.7.dev2.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
154
- shotgun_sh-0.2.7.dev2.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
155
- shotgun_sh-0.2.7.dev2.dist-info/RECORD,,
151
+ shotgun_sh-0.2.8.dev1.dist-info/METADATA,sha256=razgwSFigJNH56uBlRPZ8yxyQjjvThAbMZpHlPI4_JY,4335
152
+ shotgun_sh-0.2.8.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
153
+ shotgun_sh-0.2.8.dev1.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
154
+ shotgun_sh-0.2.8.dev1.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
155
+ shotgun_sh-0.2.8.dev1.dist-info/RECORD,,