shotgun-sh 0.1.11.dev1__tar.gz → 0.1.12.dev2__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.dev1 → shotgun_sh-0.1.12.dev2}/PKG-INFO +1 -1
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/pyproject.toml +1 -1
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/vertical_tail.py +6 -0
- shotgun_sh-0.1.12.dev2/src/shotgun/tui/filtered_codebase_service.py +46 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat.py +23 -122
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/history.py +26 -9
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/.gitignore +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/LICENSE +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/README.md +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/hatch_build.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/agent_manager.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/common.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/config/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/config/constants.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/config/manager.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/config/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/config/provider.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/conversation_history.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/conversation_manager.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/export.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/compaction.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/constants.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/context_extraction.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/history_building.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/history_processors.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/message_utils.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/token_counting.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/token_estimation.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/messages.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/plan.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/research.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/specify.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tasks.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/codebase_shell.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/directory_lister.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/file_read.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/query_graph.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/retrieve_code.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/file_management.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/user_interaction.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/anthropic.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/gemini.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/openai.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/utils.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/build_constants.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/codebase/commands.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/codebase/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/config.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/export.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/plan.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/research.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/specify.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/tasks.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/update.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/cli/utils.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/change_detector.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/code_retrieval.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/cypher_models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/ingestor.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/language_config.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/manager.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/nl_query.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/parser_loader.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/service.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/logging_config.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/main.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/posthog_telemetry.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/export.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/partials/codebase_understanding.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/partials/content_formatting.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/partials/interactive_mode.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/plan.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/research.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/specify.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/state/system_state.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/tasks.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/cypher_query_patterns.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/cypher_system.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/enhanced_query_context.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/partials/cypher_rules.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/partials/graph_schema.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/partials/temporal_context.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/history/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/history/incremental_summarization.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/history/summarization.j2 +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/loader.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/py.typed +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sdk/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sdk/codebase.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sdk/exceptions.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sdk/models.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sdk/services.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/sentry_telemetry.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/telemetry.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/app.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/commands/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/prompt_input.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/spinner.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/splash.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat.tcss +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/command_providers.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/hint_message.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/directory_setup.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/provider_config.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/splash.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/styles.tcss +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/utils/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/utils/mode_progress.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/utils/__init__.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/utils/env_utils.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/utils/file_system_utils.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/utils/source_detection.py +0 -0
- {shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/utils/update_checker.py +0 -0
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/vertical_tail.py
RENAMED
|
@@ -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
|
|
@@ -20,7 +19,7 @@ from textual.containers import Container, Grid
|
|
|
20
19
|
from textual.reactive import reactive
|
|
21
20
|
from textual.screen import ModalScreen, Screen
|
|
22
21
|
from textual.widget import Widget
|
|
23
|
-
from textual.widgets import Button,
|
|
22
|
+
from textual.widgets import Button, Label, Markdown, Static
|
|
24
23
|
|
|
25
24
|
from shotgun.agents.agent_manager import (
|
|
26
25
|
AgentManager,
|
|
@@ -44,10 +43,11 @@ from shotgun.codebase.core.manager import CodebaseAlreadyIndexedError
|
|
|
44
43
|
from shotgun.posthog_telemetry import track_event
|
|
45
44
|
from shotgun.sdk.codebase import CodebaseSDK
|
|
46
45
|
from shotgun.sdk.exceptions import CodebaseNotFoundError, InvalidPathError
|
|
47
|
-
from shotgun.sdk.services import get_codebase_service
|
|
48
46
|
from shotgun.tui.commands import CommandHandler
|
|
47
|
+
from shotgun.tui.filtered_codebase_service import FilteredCodebaseService
|
|
49
48
|
from shotgun.tui.screens.chat_screen.hint_message import HintMessage
|
|
50
49
|
from shotgun.tui.screens.chat_screen.history import ChatHistory
|
|
50
|
+
from shotgun.utils import get_shotgun_home
|
|
51
51
|
|
|
52
52
|
from ..components.prompt_input import PromptInput
|
|
53
53
|
from ..components.spinner import Spinner
|
|
@@ -167,11 +167,6 @@ class ModeIndicator(Widget):
|
|
|
167
167
|
return f"[bold $text-accent]{mode_title}{status_icon} mode[/][$foreground-muted] ({description})[/]"
|
|
168
168
|
|
|
169
169
|
|
|
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
170
|
class CodebaseIndexPromptScreen(ModalScreen[bool]):
|
|
176
171
|
"""Modal dialog asking whether to index the detected codebase."""
|
|
177
172
|
|
|
@@ -226,105 +221,6 @@ class CodebaseIndexPromptScreen(ModalScreen[bool]):
|
|
|
226
221
|
self.dismiss(True)
|
|
227
222
|
|
|
228
223
|
|
|
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
224
|
class ChatScreen(Screen[None]):
|
|
329
225
|
CSS_PATH = "chat.tcss"
|
|
330
226
|
|
|
@@ -349,7 +245,9 @@ class ChatScreen(Screen[None]):
|
|
|
349
245
|
super().__init__()
|
|
350
246
|
# Get the model configuration and services
|
|
351
247
|
model_config = get_provider_model()
|
|
352
|
-
|
|
248
|
+
# Use filtered service in TUI to restrict access to CWD codebase only
|
|
249
|
+
storage_dir = get_shotgun_home() / "codebases"
|
|
250
|
+
codebase_service = FilteredCodebaseService(storage_dir)
|
|
353
251
|
self.codebase_sdk = CodebaseSDK()
|
|
354
252
|
|
|
355
253
|
# Create shared deps without system_prompt_fn (agents provide their own)
|
|
@@ -423,6 +321,7 @@ class ChatScreen(Screen[None]):
|
|
|
423
321
|
self.mount_hint(help_text_with_codebase(already_indexed=True))
|
|
424
322
|
return
|
|
425
323
|
|
|
324
|
+
# Ask user if they want to index the current directory
|
|
426
325
|
should_index = await self.app.push_screen_wait(CodebaseIndexPromptScreen())
|
|
427
326
|
if not should_index:
|
|
428
327
|
self.mount_hint(help_text_empty_dir())
|
|
@@ -430,7 +329,10 @@ class ChatScreen(Screen[None]):
|
|
|
430
329
|
|
|
431
330
|
self.mount_hint(help_text_with_codebase(already_indexed=False))
|
|
432
331
|
|
|
433
|
-
|
|
332
|
+
# Auto-index the current directory with its name
|
|
333
|
+
cwd_name = cur_dir.name
|
|
334
|
+
selection = CodebaseIndexSelection(repo_path=cur_dir, name=cwd_name)
|
|
335
|
+
self.call_later(lambda: self.index_codebase(selection))
|
|
434
336
|
|
|
435
337
|
def watch_mode(self, new_mode: AgentType) -> None:
|
|
436
338
|
"""React to mode changes by updating the agent manager."""
|
|
@@ -529,12 +431,16 @@ class ChatScreen(Screen[None]):
|
|
|
529
431
|
@on(PartialResponseMessage)
|
|
530
432
|
def handle_partial_response(self, event: PartialResponseMessage) -> None:
|
|
531
433
|
self.partial_message = event.message
|
|
532
|
-
|
|
533
434
|
history = self.query_one(ChatHistory)
|
|
534
|
-
|
|
535
|
-
|
|
435
|
+
|
|
436
|
+
# Only update messages if the message list changed
|
|
437
|
+
new_message_list = self.messages + cast(
|
|
438
|
+
list[ModelMessage | HintMessage], event.messages
|
|
536
439
|
)
|
|
440
|
+
if len(new_message_list) != len(history.items):
|
|
441
|
+
history.update_messages(new_message_list)
|
|
537
442
|
|
|
443
|
+
# Always update the partial response (reactive property handles the update)
|
|
538
444
|
history.partial_response = self.partial_message
|
|
539
445
|
|
|
540
446
|
def _clear_partial_response(self) -> None:
|
|
@@ -640,16 +546,11 @@ class ChatScreen(Screen[None]):
|
|
|
640
546
|
return self.placeholder_hints.get_placeholder_for_mode(mode)
|
|
641
547
|
|
|
642
548
|
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
|
-
)
|
|
549
|
+
# Simplified: always index current working directory with its name
|
|
550
|
+
cur_dir = Path.cwd().resolve()
|
|
551
|
+
cwd_name = cur_dir.name
|
|
552
|
+
selection = CodebaseIndexSelection(repo_path=cur_dir, name=cwd_name)
|
|
553
|
+
self.call_later(lambda: self.index_codebase(selection))
|
|
653
554
|
|
|
654
555
|
def delete_codebase_command(self) -> None:
|
|
655
556
|
self.app.push_screen(
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/history.py
RENAMED
|
@@ -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):
|
|
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.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/conversation_history.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/conversation_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/context_extraction.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/history_building.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/history_processors.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/message_utils.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/token_counting.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/history/token_estimation.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
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/file_read.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/models.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/query_graph.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/codebase/retrieve_code.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/file_management.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/user_interaction.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/__init__.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/anthropic.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/gemini.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/openai.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/agents/tools/web_search/utils.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
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/change_detector.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/code_retrieval.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/cypher_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/language_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/codebase/core/parser_loader.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
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/agents/state/system_state.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/codebase/cypher_system.j2
RENAMED
|
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.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/prompts/history/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
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/components/prompt_input.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/chat_screen/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/directory_setup.py
RENAMED
|
File without changes
|
{shotgun_sh-0.1.11.dev1 → shotgun_sh-0.1.12.dev2}/src/shotgun/tui/screens/provider_config.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
|