shotgun-sh 0.1.11__tar.gz → 0.1.12__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.1.11 → shotgun_sh-0.1.12}/PKG-INFO +1 -1
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/pyproject.toml +1 -1
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/manager.py +13 -1
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/service.py +4 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/main.py +9 -1
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/app.py +4 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/components/vertical_tail.py +6 -0
- shotgun_sh-0.1.12/src/shotgun/tui/filtered_codebase_service.py +46 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat.py +35 -126
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat_screen/history.py +110 -21
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/.gitignore +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/LICENSE +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/README.md +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/hatch_build.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/agent_manager.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/common.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/config/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/config/constants.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/config/manager.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/config/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/config/provider.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/conversation_history.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/conversation_manager.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/export.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/compaction.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/constants.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/context_extraction.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/history_building.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/history_processors.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/message_utils.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/token_counting.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/history/token_estimation.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/messages.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/plan.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/research.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/specify.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tasks.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/file_management.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/user_interaction.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/web_search/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/web_search/openai.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/web_search/utils.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/build_constants.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/codebase/commands.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/codebase/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/config.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/export.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/plan.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/research.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/specify.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/tasks.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/update.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/cli/utils.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/change_detector.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/code_retrieval.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/cypher_models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/ingestor.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/language_config.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/nl_query.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/core/parser_loader.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/codebase/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/logging_config.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/posthog_telemetry.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/export.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/plan.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/research.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/specify.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/state/system_state.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/tasks.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/history/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/history/summarization.j2 +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/loader.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/py.typed +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sdk/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sdk/codebase.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sdk/exceptions.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sdk/models.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sdk/services.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/sentry_telemetry.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/telemetry.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/commands/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/components/prompt_input.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/components/spinner.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/components/splash.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat.tcss +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat_screen/command_providers.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat_screen/hint_message.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/directory_setup.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/provider_config.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/splash.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/styles.tcss +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/utils/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/utils/mode_progress.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/utils/__init__.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/utils/env_utils.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/utils/file_system_utils.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/utils/source_detection.py +0 -0
- {shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/utils/update_checker.py +0 -0
|
@@ -353,7 +353,19 @@ class CodebaseGraphManager:
|
|
|
353
353
|
|
|
354
354
|
# Check if graph already exists
|
|
355
355
|
if graph_path.exists():
|
|
356
|
-
|
|
356
|
+
# Verify it's not corrupted by checking if we can load the Project node
|
|
357
|
+
existing_graph = await self.get_graph(graph_id)
|
|
358
|
+
if existing_graph:
|
|
359
|
+
# Valid existing graph
|
|
360
|
+
raise CodebaseAlreadyIndexedError(repo_path)
|
|
361
|
+
else:
|
|
362
|
+
# Corrupted database - remove and re-index
|
|
363
|
+
logger.warning(
|
|
364
|
+
f"Found corrupted database at {graph_path}, removing for re-indexing..."
|
|
365
|
+
)
|
|
366
|
+
import shutil
|
|
367
|
+
|
|
368
|
+
shutil.rmtree(graph_path)
|
|
357
369
|
|
|
358
370
|
# Import the builder from local core module
|
|
359
371
|
from shotgun.codebase.core import CodebaseIngestor
|
|
@@ -69,6 +69,10 @@ class CodebaseService:
|
|
|
69
69
|
# Otherwise, check if current directory is in the allowed list
|
|
70
70
|
elif target_path in graph.indexed_from_cwds:
|
|
71
71
|
filtered_graphs.append(graph)
|
|
72
|
+
# Also allow access if current directory IS the repository itself
|
|
73
|
+
# Use Path.resolve() for robust comparison (handles symlinks, etc.)
|
|
74
|
+
elif Path(target_path).resolve() == Path(graph.repo_path).resolve():
|
|
75
|
+
filtered_graphs.append(graph)
|
|
72
76
|
|
|
73
77
|
return filtered_graphs
|
|
74
78
|
|
|
@@ -118,7 +118,15 @@ def main(
|
|
|
118
118
|
|
|
119
119
|
if ctx.invoked_subcommand is None and not ctx.resilient_parsing:
|
|
120
120
|
logger.debug("Launching shotgun TUI application")
|
|
121
|
-
|
|
121
|
+
try:
|
|
122
|
+
tui_app.run(
|
|
123
|
+
no_update_check=no_update_check, continue_session=continue_session
|
|
124
|
+
)
|
|
125
|
+
finally:
|
|
126
|
+
# Ensure PostHog is shut down cleanly even if TUI exits unexpectedly
|
|
127
|
+
from shotgun.posthog_telemetry import shutdown
|
|
128
|
+
|
|
129
|
+
shutdown()
|
|
122
130
|
raise typer.Exit()
|
|
123
131
|
|
|
124
132
|
# For CLI commands, register PostHog shutdown handler
|
|
@@ -83,6 +83,10 @@ class ShotgunApp(App[None]):
|
|
|
83
83
|
|
|
84
84
|
async def action_quit(self) -> None:
|
|
85
85
|
"""Quit the application."""
|
|
86
|
+
# Shut down PostHog client to prevent threading errors
|
|
87
|
+
from shotgun.posthog_telemetry import shutdown
|
|
88
|
+
|
|
89
|
+
shutdown()
|
|
86
90
|
self.exit()
|
|
87
91
|
|
|
88
92
|
def get_system_commands(self, screen: Screen[Any]) -> Iterable[SystemCommand]:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from textual.containers import VerticalScroll
|
|
2
|
+
from textual.geometry import Size
|
|
2
3
|
from textual.reactive import reactive
|
|
3
4
|
|
|
4
5
|
|
|
@@ -11,3 +12,8 @@ class VerticalTail(VerticalScroll):
|
|
|
11
12
|
"""Handle auto_scroll property changes."""
|
|
12
13
|
if value:
|
|
13
14
|
self.scroll_end(animate=False)
|
|
15
|
+
|
|
16
|
+
def watch_virtual_size(self, value: Size) -> None:
|
|
17
|
+
"""Handle virtual_size property changes."""
|
|
18
|
+
|
|
19
|
+
self.call_later(self.scroll_end, animate=False)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Filtered codebase service that restricts access to current directory's codebase only."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from shotgun.codebase.models import CodebaseGraph
|
|
6
|
+
from shotgun.codebase.service import CodebaseService
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FilteredCodebaseService(CodebaseService):
|
|
10
|
+
"""CodebaseService subclass that filters graphs to only those accessible from CWD.
|
|
11
|
+
|
|
12
|
+
This ensures TUI agents can only see and access the codebase indexed from the
|
|
13
|
+
current working directory, providing isolation between different project directories.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, storage_dir: Path | str):
|
|
17
|
+
"""Initialize the filtered service.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
storage_dir: Directory to store graph databases
|
|
21
|
+
"""
|
|
22
|
+
super().__init__(storage_dir)
|
|
23
|
+
self._cwd = str(Path.cwd().resolve())
|
|
24
|
+
|
|
25
|
+
async def list_graphs(self) -> list[CodebaseGraph]:
|
|
26
|
+
"""List only graphs accessible from the current working directory.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Filtered list of CodebaseGraph objects accessible from CWD
|
|
30
|
+
"""
|
|
31
|
+
# Use the existing filtering logic from list_graphs_for_directory
|
|
32
|
+
return await super().list_graphs_for_directory(self._cwd)
|
|
33
|
+
|
|
34
|
+
async def list_graphs_for_directory(
|
|
35
|
+
self, directory: Path | str | None = None
|
|
36
|
+
) -> list[CodebaseGraph]:
|
|
37
|
+
"""List graphs for directory - always filters to CWD for TUI context.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
directory: Ignored in TUI context, always uses CWD
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Filtered list of CodebaseGraph objects accessible from CWD
|
|
44
|
+
"""
|
|
45
|
+
# Always use CWD regardless of what directory is passed
|
|
46
|
+
return await super().list_graphs_for_directory(self._cwd)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
-
from collections.abc import Iterable
|
|
4
3
|
from dataclasses import dataclass
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from typing import cast
|
|
@@ -17,10 +16,11 @@ from textual import events, on, work
|
|
|
17
16
|
from textual.app import ComposeResult
|
|
18
17
|
from textual.command import CommandPalette
|
|
19
18
|
from textual.containers import Container, Grid
|
|
19
|
+
from textual.keys import Keys
|
|
20
20
|
from textual.reactive import reactive
|
|
21
21
|
from textual.screen import ModalScreen, Screen
|
|
22
22
|
from textual.widget import Widget
|
|
23
|
-
from textual.widgets import Button,
|
|
23
|
+
from textual.widgets import Button, Label, Markdown, Static
|
|
24
24
|
|
|
25
25
|
from shotgun.agents.agent_manager import (
|
|
26
26
|
AgentManager,
|
|
@@ -44,10 +44,11 @@ from shotgun.codebase.core.manager import CodebaseAlreadyIndexedError
|
|
|
44
44
|
from shotgun.posthog_telemetry import track_event
|
|
45
45
|
from shotgun.sdk.codebase import CodebaseSDK
|
|
46
46
|
from shotgun.sdk.exceptions import CodebaseNotFoundError, InvalidPathError
|
|
47
|
-
from shotgun.sdk.services import get_codebase_service
|
|
48
47
|
from shotgun.tui.commands import CommandHandler
|
|
48
|
+
from shotgun.tui.filtered_codebase_service import FilteredCodebaseService
|
|
49
49
|
from shotgun.tui.screens.chat_screen.hint_message import HintMessage
|
|
50
50
|
from shotgun.tui.screens.chat_screen.history import ChatHistory
|
|
51
|
+
from shotgun.utils import get_shotgun_home
|
|
51
52
|
|
|
52
53
|
from ..components.prompt_input import PromptInput
|
|
53
54
|
from ..components.spinner import Spinner
|
|
@@ -167,11 +168,6 @@ class ModeIndicator(Widget):
|
|
|
167
168
|
return f"[bold $text-accent]{mode_title}{status_icon} mode[/][$foreground-muted] ({description})[/]"
|
|
168
169
|
|
|
169
170
|
|
|
170
|
-
class FilteredDirectoryTree(DirectoryTree):
|
|
171
|
-
def filter_paths(self, paths: Iterable[Path]) -> Iterable[Path]:
|
|
172
|
-
return [path for path in paths if path.is_dir()]
|
|
173
|
-
|
|
174
|
-
|
|
175
171
|
class CodebaseIndexPromptScreen(ModalScreen[bool]):
|
|
176
172
|
"""Modal dialog asking whether to index the detected codebase."""
|
|
177
173
|
|
|
@@ -226,105 +222,6 @@ class CodebaseIndexPromptScreen(ModalScreen[bool]):
|
|
|
226
222
|
self.dismiss(True)
|
|
227
223
|
|
|
228
224
|
|
|
229
|
-
class CodebaseIndexScreen(ModalScreen[CodebaseIndexSelection | None]):
|
|
230
|
-
"""Modal dialog for choosing a repository and name to index."""
|
|
231
|
-
|
|
232
|
-
DEFAULT_CSS = """
|
|
233
|
-
CodebaseIndexScreen {
|
|
234
|
-
align: center middle;
|
|
235
|
-
background: rgba(0, 0, 0, 0.0);
|
|
236
|
-
}
|
|
237
|
-
CodebaseIndexScreen > #index-dialog {
|
|
238
|
-
width: 80%;
|
|
239
|
-
max-width: 80;
|
|
240
|
-
height: 80%;
|
|
241
|
-
max-height: 40;
|
|
242
|
-
border: wide $primary;
|
|
243
|
-
padding: 1;
|
|
244
|
-
layout: vertical;
|
|
245
|
-
background: $surface;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
#index-dialog DirectoryTree {
|
|
249
|
-
height: 1fr;
|
|
250
|
-
border: solid $accent;
|
|
251
|
-
overflow: auto;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
#index-dialog-controls {
|
|
255
|
-
layout: horizontal;
|
|
256
|
-
align-horizontal: right;
|
|
257
|
-
padding-top: 1;
|
|
258
|
-
}
|
|
259
|
-
"""
|
|
260
|
-
|
|
261
|
-
def __init__(self, start_path: Path | None = None) -> None:
|
|
262
|
-
super().__init__()
|
|
263
|
-
self.start_path = Path(start_path or Path.cwd())
|
|
264
|
-
self.selected_path: Path | None = self.start_path
|
|
265
|
-
|
|
266
|
-
def compose(self) -> ComposeResult:
|
|
267
|
-
with Container(id="index-dialog"):
|
|
268
|
-
yield Label("Index a codebase", id="index-dialog-title")
|
|
269
|
-
yield FilteredDirectoryTree(self.start_path, id="index-directory-tree")
|
|
270
|
-
yield Input(
|
|
271
|
-
placeholder="Enter a name for the codebase",
|
|
272
|
-
id="index-codebase-name",
|
|
273
|
-
)
|
|
274
|
-
with Container(id="index-dialog-controls"):
|
|
275
|
-
yield Button("Cancel", id="index-cancel")
|
|
276
|
-
yield Button(
|
|
277
|
-
"Index",
|
|
278
|
-
id="index-confirm",
|
|
279
|
-
variant="primary",
|
|
280
|
-
disabled=True,
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
def on_mount(self) -> None:
|
|
284
|
-
name_input = self.query_one("#index-codebase-name", Input)
|
|
285
|
-
if not name_input.value and self.selected_path:
|
|
286
|
-
name_input.value = self.selected_path.name
|
|
287
|
-
self._update_confirm()
|
|
288
|
-
|
|
289
|
-
def _update_confirm(self) -> None:
|
|
290
|
-
confirm = self.query_one("#index-confirm", Button)
|
|
291
|
-
name_input = self.query_one("#index-codebase-name", Input)
|
|
292
|
-
confirm.disabled = not (self.selected_path and name_input.value.strip())
|
|
293
|
-
|
|
294
|
-
@on(DirectoryTree.DirectorySelected, "#index-directory-tree")
|
|
295
|
-
def handle_directory_selected(self, event: DirectoryTree.DirectorySelected) -> None:
|
|
296
|
-
event.stop()
|
|
297
|
-
selected = event.path if event.path.is_dir() else event.path.parent
|
|
298
|
-
self.selected_path = selected
|
|
299
|
-
name_input = self.query_one("#index-codebase-name", Input)
|
|
300
|
-
if not name_input.value:
|
|
301
|
-
name_input.value = selected.name
|
|
302
|
-
self._update_confirm()
|
|
303
|
-
|
|
304
|
-
@on(Input.Changed, "#index-codebase-name")
|
|
305
|
-
def handle_name_changed(self, event: Input.Changed) -> None:
|
|
306
|
-
event.stop()
|
|
307
|
-
self._update_confirm()
|
|
308
|
-
|
|
309
|
-
@on(Button.Pressed, "#index-cancel")
|
|
310
|
-
def handle_cancel(self, event: Button.Pressed) -> None:
|
|
311
|
-
event.stop()
|
|
312
|
-
self.dismiss(None)
|
|
313
|
-
|
|
314
|
-
@on(Button.Pressed, "#index-confirm")
|
|
315
|
-
def handle_confirm(self, event: Button.Pressed) -> None:
|
|
316
|
-
event.stop()
|
|
317
|
-
name_input = self.query_one("#index-codebase-name", Input)
|
|
318
|
-
if not self.selected_path:
|
|
319
|
-
self.dismiss(None)
|
|
320
|
-
return
|
|
321
|
-
selection = CodebaseIndexSelection(
|
|
322
|
-
repo_path=self.selected_path,
|
|
323
|
-
name=name_input.value.strip(),
|
|
324
|
-
)
|
|
325
|
-
self.dismiss(selection)
|
|
326
|
-
|
|
327
|
-
|
|
328
225
|
class ChatScreen(Screen[None]):
|
|
329
226
|
CSS_PATH = "chat.tcss"
|
|
330
227
|
|
|
@@ -349,7 +246,9 @@ class ChatScreen(Screen[None]):
|
|
|
349
246
|
super().__init__()
|
|
350
247
|
# Get the model configuration and services
|
|
351
248
|
model_config = get_provider_model()
|
|
352
|
-
|
|
249
|
+
# Use filtered service in TUI to restrict access to CWD codebase only
|
|
250
|
+
storage_dir = get_shotgun_home() / "codebases"
|
|
251
|
+
codebase_service = FilteredCodebaseService(storage_dir)
|
|
353
252
|
self.codebase_sdk = CodebaseSDK()
|
|
354
253
|
|
|
355
254
|
# Create shared deps without system_prompt_fn (agents provide their own)
|
|
@@ -387,13 +286,18 @@ class ChatScreen(Screen[None]):
|
|
|
387
286
|
|
|
388
287
|
async def on_key(self, event: events.Key) -> None:
|
|
389
288
|
"""Handle key presses for cancellation."""
|
|
390
|
-
# If escape is pressed while agent is working, cancel the operation
|
|
391
|
-
if
|
|
392
|
-
|
|
289
|
+
# If escape or ctrl+c is pressed while agent is working, cancel the operation
|
|
290
|
+
if (
|
|
291
|
+
event.key in (Keys.Escape, Keys.ControlC)
|
|
292
|
+
and self.working
|
|
293
|
+
and self._current_worker
|
|
294
|
+
):
|
|
295
|
+
# Track cancellation event
|
|
393
296
|
track_event(
|
|
394
|
-
"
|
|
297
|
+
"agent_cancelled",
|
|
395
298
|
{
|
|
396
299
|
"agent_mode": self.mode.value,
|
|
300
|
+
"cancel_key": event.key,
|
|
397
301
|
},
|
|
398
302
|
)
|
|
399
303
|
|
|
@@ -404,6 +308,8 @@ class ChatScreen(Screen[None]):
|
|
|
404
308
|
# Re-enable the input
|
|
405
309
|
prompt_input = self.query_one(PromptInput)
|
|
406
310
|
prompt_input.focus()
|
|
311
|
+
# Prevent the event from propagating (don't quit the app)
|
|
312
|
+
event.stop()
|
|
407
313
|
|
|
408
314
|
@work
|
|
409
315
|
async def check_if_codebase_is_indexed(self) -> None:
|
|
@@ -423,6 +329,7 @@ class ChatScreen(Screen[None]):
|
|
|
423
329
|
self.mount_hint(help_text_with_codebase(already_indexed=True))
|
|
424
330
|
return
|
|
425
331
|
|
|
332
|
+
# Ask user if they want to index the current directory
|
|
426
333
|
should_index = await self.app.push_screen_wait(CodebaseIndexPromptScreen())
|
|
427
334
|
if not should_index:
|
|
428
335
|
self.mount_hint(help_text_empty_dir())
|
|
@@ -430,7 +337,10 @@ class ChatScreen(Screen[None]):
|
|
|
430
337
|
|
|
431
338
|
self.mount_hint(help_text_with_codebase(already_indexed=False))
|
|
432
339
|
|
|
433
|
-
|
|
340
|
+
# Auto-index the current directory with its name
|
|
341
|
+
cwd_name = cur_dir.name
|
|
342
|
+
selection = CodebaseIndexSelection(repo_path=cur_dir, name=cwd_name)
|
|
343
|
+
self.call_later(lambda: self.index_codebase(selection))
|
|
434
344
|
|
|
435
345
|
def watch_mode(self, new_mode: AgentType) -> None:
|
|
436
346
|
"""React to mode changes by updating the agent manager."""
|
|
@@ -529,12 +439,16 @@ class ChatScreen(Screen[None]):
|
|
|
529
439
|
@on(PartialResponseMessage)
|
|
530
440
|
def handle_partial_response(self, event: PartialResponseMessage) -> None:
|
|
531
441
|
self.partial_message = event.message
|
|
532
|
-
|
|
533
442
|
history = self.query_one(ChatHistory)
|
|
534
|
-
|
|
535
|
-
|
|
443
|
+
|
|
444
|
+
# Only update messages if the message list changed
|
|
445
|
+
new_message_list = self.messages + cast(
|
|
446
|
+
list[ModelMessage | HintMessage], event.messages
|
|
536
447
|
)
|
|
448
|
+
if len(new_message_list) != len(history.items):
|
|
449
|
+
history.update_messages(new_message_list)
|
|
537
450
|
|
|
451
|
+
# Always update the partial response (reactive property handles the update)
|
|
538
452
|
history.partial_response = self.partial_message
|
|
539
453
|
|
|
540
454
|
def _clear_partial_response(self) -> None:
|
|
@@ -640,16 +554,11 @@ class ChatScreen(Screen[None]):
|
|
|
640
554
|
return self.placeholder_hints.get_placeholder_for_mode(mode)
|
|
641
555
|
|
|
642
556
|
def index_codebase_command(self) -> None:
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
self.app.push_screen(
|
|
650
|
-
CodebaseIndexScreen(start_path=start_path),
|
|
651
|
-
handle_result,
|
|
652
|
-
)
|
|
557
|
+
# Simplified: always index current working directory with its name
|
|
558
|
+
cur_dir = Path.cwd().resolve()
|
|
559
|
+
cwd_name = cur_dir.name
|
|
560
|
+
selection = CodebaseIndexSelection(repo_path=cur_dir, name=cwd_name)
|
|
561
|
+
self.call_later(lambda: self.index_codebase(selection))
|
|
653
562
|
|
|
654
563
|
def delete_codebase_command(self) -> None:
|
|
655
564
|
self.app.push_screen(
|
|
@@ -41,7 +41,6 @@ class PartialResponseWidget(Widget): # TODO: doesn't work lol
|
|
|
41
41
|
self.item = item
|
|
42
42
|
|
|
43
43
|
def compose(self) -> ComposeResult:
|
|
44
|
-
yield Markdown(markdown="**partial response**")
|
|
45
44
|
if self.item is None:
|
|
46
45
|
pass
|
|
47
46
|
elif self.item.kind == "response":
|
|
@@ -82,12 +81,14 @@ class ChatHistory(Widget):
|
|
|
82
81
|
self.items: Sequence[ModelMessage | HintMessage] = []
|
|
83
82
|
self.vertical_tail: VerticalTail | None = None
|
|
84
83
|
self.partial_response = None
|
|
84
|
+
self._rendered_count = 0 # Track how many messages have been mounted
|
|
85
85
|
|
|
86
86
|
def compose(self) -> ComposeResult:
|
|
87
87
|
self.vertical_tail = VerticalTail()
|
|
88
88
|
|
|
89
|
+
filtered = list(self.filtered_items())
|
|
89
90
|
with self.vertical_tail:
|
|
90
|
-
for item in
|
|
91
|
+
for item in filtered:
|
|
91
92
|
if isinstance(item, ModelRequest):
|
|
92
93
|
yield UserQuestionWidget(item)
|
|
93
94
|
elif isinstance(item, HintMessage):
|
|
@@ -97,7 +98,9 @@ class ChatHistory(Widget):
|
|
|
97
98
|
yield PartialResponseWidget(self.partial_response).data_bind(
|
|
98
99
|
item=ChatHistory.partial_response
|
|
99
100
|
)
|
|
100
|
-
|
|
101
|
+
|
|
102
|
+
# Track how many messages were rendered during initial compose
|
|
103
|
+
self._rendered_count = len(filtered)
|
|
101
104
|
|
|
102
105
|
def filtered_items(self) -> Generator[ModelMessage | HintMessage, None, None]:
|
|
103
106
|
for idx, next_item in enumerate(self.items):
|
|
@@ -138,17 +141,31 @@ class ChatHistory(Widget):
|
|
|
138
141
|
yield next_item
|
|
139
142
|
|
|
140
143
|
def update_messages(self, messages: list[ModelMessage | HintMessage]) -> None:
|
|
141
|
-
"""Update the displayed messages
|
|
144
|
+
"""Update the displayed messages using incremental mounting."""
|
|
142
145
|
if not self.vertical_tail:
|
|
143
146
|
return
|
|
144
147
|
|
|
145
148
|
self.items = messages
|
|
146
|
-
self.
|
|
147
|
-
|
|
149
|
+
filtered = list(self.filtered_items())
|
|
150
|
+
|
|
151
|
+
# Only mount new messages that haven't been rendered yet
|
|
152
|
+
if len(filtered) > self._rendered_count:
|
|
153
|
+
new_messages = filtered[self._rendered_count :]
|
|
154
|
+
for item in new_messages:
|
|
155
|
+
widget: Widget
|
|
156
|
+
if isinstance(item, ModelRequest):
|
|
157
|
+
widget = UserQuestionWidget(item)
|
|
158
|
+
elif isinstance(item, HintMessage):
|
|
159
|
+
widget = HintMessageWidget(item)
|
|
160
|
+
elif isinstance(item, ModelResponse):
|
|
161
|
+
widget = AgentResponseWidget(item)
|
|
162
|
+
else:
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
# Mount before the PartialResponseWidget
|
|
166
|
+
self.vertical_tail.mount(widget, before=self.vertical_tail.children[-1])
|
|
148
167
|
|
|
149
|
-
|
|
150
|
-
if self.vertical_tail:
|
|
151
|
-
self.vertical_tail.scroll_end(animate=False, immediate=False, force=True)
|
|
168
|
+
self._rendered_count = len(filtered)
|
|
152
169
|
|
|
153
170
|
|
|
154
171
|
class UserQuestionWidget(Widget):
|
|
@@ -221,25 +238,97 @@ class AgentResponseWidget(Widget):
|
|
|
221
238
|
continue
|
|
222
239
|
return acc.strip()
|
|
223
240
|
|
|
241
|
+
def _truncate(self, text: str, max_length: int = 100) -> str:
|
|
242
|
+
"""Truncate text to max_length characters, adding ellipsis if needed."""
|
|
243
|
+
if len(text) <= max_length:
|
|
244
|
+
return text
|
|
245
|
+
return text[: max_length - 3] + "..."
|
|
246
|
+
|
|
247
|
+
def _parse_args(self, args: dict[str, object] | str | None) -> dict[str, object]:
|
|
248
|
+
"""Parse tool call arguments, handling both dict and JSON string formats."""
|
|
249
|
+
if args is None:
|
|
250
|
+
return {}
|
|
251
|
+
if isinstance(args, str):
|
|
252
|
+
try:
|
|
253
|
+
return json.loads(args) if args.strip() else {}
|
|
254
|
+
except json.JSONDecodeError:
|
|
255
|
+
return {}
|
|
256
|
+
return args if isinstance(args, dict) else {}
|
|
257
|
+
|
|
224
258
|
def _format_tool_call_part(self, part: ToolCallPart) -> str:
|
|
225
259
|
if part.tool_name == "ask_user":
|
|
226
260
|
return self._format_ask_user_part(part)
|
|
261
|
+
|
|
262
|
+
# Parse args once (handles both JSON string and dict)
|
|
263
|
+
args = self._parse_args(part.args)
|
|
264
|
+
|
|
265
|
+
# Codebase tools - show friendly names
|
|
266
|
+
if part.tool_name == "query_graph":
|
|
267
|
+
if "query" in args:
|
|
268
|
+
query = self._truncate(str(args["query"]))
|
|
269
|
+
return f'Querying code: "{query}"'
|
|
270
|
+
return "Querying code"
|
|
271
|
+
|
|
272
|
+
if part.tool_name == "retrieve_code":
|
|
273
|
+
if "qualified_name" in args:
|
|
274
|
+
return f'Retrieving code: "{args["qualified_name"]}"'
|
|
275
|
+
return "Retrieving code"
|
|
276
|
+
|
|
277
|
+
if part.tool_name == "file_read":
|
|
278
|
+
if "file_path" in args:
|
|
279
|
+
return f'Reading file: "{args["file_path"]}"'
|
|
280
|
+
return "Reading file"
|
|
281
|
+
|
|
282
|
+
if part.tool_name == "directory_lister":
|
|
283
|
+
if "directory" in args:
|
|
284
|
+
return f'Listing directory: "{args["directory"]}"'
|
|
285
|
+
return "Listing directory"
|
|
286
|
+
|
|
287
|
+
if part.tool_name == "codebase_shell":
|
|
288
|
+
command = args.get("command", "")
|
|
289
|
+
cmd_args = args.get("args", [])
|
|
290
|
+
# Handle cmd_args as list of strings
|
|
291
|
+
if isinstance(cmd_args, list):
|
|
292
|
+
args_str = " ".join(str(arg) for arg in cmd_args)
|
|
293
|
+
else:
|
|
294
|
+
args_str = ""
|
|
295
|
+
full_cmd = f"{command} {args_str}".strip()
|
|
296
|
+
if full_cmd:
|
|
297
|
+
return f'Running shell: "{self._truncate(full_cmd)}"'
|
|
298
|
+
return "Running shell"
|
|
299
|
+
|
|
300
|
+
# File management tools
|
|
301
|
+
if part.tool_name == "read_file":
|
|
302
|
+
if "filename" in args:
|
|
303
|
+
return f'Reading file: "{args["filename"]}"'
|
|
304
|
+
return "Reading file"
|
|
305
|
+
|
|
306
|
+
# Web search tools
|
|
307
|
+
if part.tool_name in [
|
|
308
|
+
"openai_web_search_tool",
|
|
309
|
+
"anthropic_web_search_tool",
|
|
310
|
+
"gemini_web_search_tool",
|
|
311
|
+
]:
|
|
312
|
+
if "query" in args:
|
|
313
|
+
query = self._truncate(str(args["query"]))
|
|
314
|
+
return f'Searching web: "{query}"'
|
|
315
|
+
return "Searching web"
|
|
316
|
+
|
|
227
317
|
# write_file
|
|
228
318
|
if part.tool_name == "write_file" or part.tool_name == "append_file":
|
|
229
|
-
if
|
|
230
|
-
return f"{part.tool_name}({
|
|
231
|
-
|
|
232
|
-
|
|
319
|
+
if "filename" in args:
|
|
320
|
+
return f"{part.tool_name}({args['filename']})"
|
|
321
|
+
return f"{part.tool_name}()"
|
|
322
|
+
|
|
233
323
|
if part.tool_name == "write_artifact_section":
|
|
234
|
-
if
|
|
235
|
-
return f"{part.tool_name}({
|
|
236
|
-
|
|
237
|
-
|
|
324
|
+
if "section_title" in args:
|
|
325
|
+
return f"{part.tool_name}({args['section_title']})"
|
|
326
|
+
return f"{part.tool_name}()"
|
|
327
|
+
|
|
238
328
|
if part.tool_name == "create_artifact":
|
|
239
|
-
if
|
|
240
|
-
return f"{part.tool_name}({
|
|
241
|
-
|
|
242
|
-
return f"▪ {part.tool_name}()"
|
|
329
|
+
if "name" in args:
|
|
330
|
+
return f"{part.tool_name}({args['name']})"
|
|
331
|
+
return f"▪ {part.tool_name}()"
|
|
243
332
|
|
|
244
333
|
return f"{part.tool_name}({part.args})"
|
|
245
334
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/agents/tools/codebase/directory_lister.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/content_formatting.j2
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/agents/partials/interactive_mode.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/cypher_query_patterns.j2
RENAMED
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/enhanced_query_context.j2
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/cypher_rules.j2
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/graph_schema.j2
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/codebase/partials/temporal_context.j2
RENAMED
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/prompts/history/incremental_summarization.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11 → shotgun_sh-0.1.12}/src/shotgun/tui/screens/chat_screen/command_providers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|