shotgun-sh 0.1.15.dev1__py3-none-any.whl → 0.2.1.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.

Files changed (39) hide show
  1. shotgun/agents/common.py +4 -5
  2. shotgun/agents/config/constants.py +21 -5
  3. shotgun/agents/config/manager.py +147 -39
  4. shotgun/agents/config/models.py +59 -86
  5. shotgun/agents/config/provider.py +164 -61
  6. shotgun/agents/history/compaction.py +1 -1
  7. shotgun/agents/history/history_processors.py +18 -9
  8. shotgun/agents/history/token_counting/__init__.py +31 -0
  9. shotgun/agents/history/token_counting/anthropic.py +89 -0
  10. shotgun/agents/history/token_counting/base.py +67 -0
  11. shotgun/agents/history/token_counting/openai.py +80 -0
  12. shotgun/agents/history/token_counting/sentencepiece_counter.py +119 -0
  13. shotgun/agents/history/token_counting/tokenizer_cache.py +90 -0
  14. shotgun/agents/history/token_counting/utils.py +147 -0
  15. shotgun/agents/history/token_estimation.py +12 -12
  16. shotgun/agents/llm.py +62 -0
  17. shotgun/agents/models.py +2 -2
  18. shotgun/agents/tools/web_search/__init__.py +42 -15
  19. shotgun/agents/tools/web_search/anthropic.py +46 -40
  20. shotgun/agents/tools/web_search/gemini.py +31 -20
  21. shotgun/agents/tools/web_search/openai.py +4 -4
  22. shotgun/cli/config.py +14 -55
  23. shotgun/cli/models.py +2 -2
  24. shotgun/codebase/models.py +4 -4
  25. shotgun/llm_proxy/__init__.py +16 -0
  26. shotgun/llm_proxy/clients.py +39 -0
  27. shotgun/llm_proxy/constants.py +8 -0
  28. shotgun/main.py +6 -0
  29. shotgun/posthog_telemetry.py +5 -3
  30. shotgun/tui/app.py +2 -0
  31. shotgun/tui/screens/chat_screen/command_providers.py +20 -0
  32. shotgun/tui/screens/model_picker.py +214 -0
  33. shotgun/tui/screens/provider_config.py +39 -26
  34. {shotgun_sh-0.1.15.dev1.dist-info → shotgun_sh-0.2.1.dev1.dist-info}/METADATA +2 -2
  35. {shotgun_sh-0.1.15.dev1.dist-info → shotgun_sh-0.2.1.dev1.dist-info}/RECORD +38 -27
  36. shotgun/agents/history/token_counting.py +0 -429
  37. {shotgun_sh-0.1.15.dev1.dist-info → shotgun_sh-0.2.1.dev1.dist-info}/WHEEL +0 -0
  38. {shotgun_sh-0.1.15.dev1.dist-info → shotgun_sh-0.2.1.dev1.dist-info}/entry_points.txt +0 -0
  39. {shotgun_sh-0.1.15.dev1.dist-info → shotgun_sh-0.2.1.dev1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,214 @@
1
+ """Screen for selecting AI model."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, cast
6
+
7
+ from textual import on
8
+ from textual.app import ComposeResult
9
+ from textual.containers import Horizontal, Vertical
10
+ from textual.reactive import reactive
11
+ from textual.screen import Screen
12
+ from textual.widgets import Button, Label, ListItem, ListView, Static
13
+
14
+ from shotgun.agents.config import ConfigManager
15
+ from shotgun.agents.config.models import MODEL_SPECS, ModelName
16
+
17
+ if TYPE_CHECKING:
18
+ from ..app import ShotgunApp
19
+
20
+
21
+ # Available models for selection
22
+ AVAILABLE_MODELS = list(ModelName)
23
+
24
+
25
+ def _sanitize_model_name_for_id(model_name: ModelName) -> str:
26
+ """Convert model name to valid Textual ID by replacing dots with hyphens."""
27
+ return model_name.value.replace(".", "-")
28
+
29
+
30
+ class ModelPickerScreen(Screen[None]):
31
+ """Select AI model to use."""
32
+
33
+ CSS = """
34
+ ModelPicker {
35
+ layout: vertical;
36
+ }
37
+
38
+ ModelPicker > * {
39
+ height: auto;
40
+ }
41
+
42
+ #titlebox {
43
+ height: auto;
44
+ margin: 2 0;
45
+ padding: 1;
46
+ border: hkey $border;
47
+ content-align: center middle;
48
+
49
+ & > * {
50
+ text-align: center;
51
+ }
52
+ }
53
+
54
+ #model-picker-title {
55
+ padding: 1 0;
56
+ text-style: bold;
57
+ color: $text-accent;
58
+ }
59
+
60
+ #model-list {
61
+ margin: 2 0;
62
+ height: auto;
63
+ & > * {
64
+ padding: 1 0;
65
+ }
66
+ }
67
+ #model-actions {
68
+ padding: 1;
69
+ }
70
+ #model-actions > * {
71
+ margin-right: 2;
72
+ }
73
+ #model-list {
74
+ padding: 1;
75
+ }
76
+ """
77
+
78
+ BINDINGS = [
79
+ ("escape", "done", "Back"),
80
+ ]
81
+
82
+ selected_model: reactive[ModelName] = reactive(ModelName.GPT_5)
83
+
84
+ def compose(self) -> ComposeResult:
85
+ with Vertical(id="titlebox"):
86
+ yield Static("Model selection", id="model-picker-title")
87
+ yield Static(
88
+ "Select the AI model you want to use for your tasks.",
89
+ id="model-picker-summary",
90
+ )
91
+ yield ListView(*self._build_model_items(), id="model-list")
92
+ with Horizontal(id="model-actions"):
93
+ yield Button("Select \\[ENTER]", variant="primary", id="select")
94
+ yield Button("Done \\[ESC]", id="done")
95
+
96
+ def on_mount(self) -> None:
97
+ # Load current selection
98
+ config_manager = self.config_manager
99
+ config = config_manager.load()
100
+ current_model = config.selected_model or ModelName.CLAUDE_OPUS_4_1
101
+ self.selected_model = current_model
102
+
103
+ # Find and highlight current selection
104
+ list_view = self.query_one(ListView)
105
+ if list_view.children:
106
+ for i, model_name in enumerate(AVAILABLE_MODELS):
107
+ if model_name == current_model:
108
+ list_view.index = i
109
+ break
110
+ self.refresh_model_labels()
111
+
112
+ def action_done(self) -> None:
113
+ self.dismiss()
114
+
115
+ @on(ListView.Highlighted)
116
+ def _on_model_highlighted(self, event: ListView.Highlighted) -> None:
117
+ model_name = self._model_from_item(event.item)
118
+ if model_name:
119
+ self.selected_model = model_name
120
+
121
+ @on(ListView.Selected)
122
+ def _on_model_selected(self, event: ListView.Selected) -> None:
123
+ model_name = self._model_from_item(event.item)
124
+ if model_name:
125
+ self.selected_model = model_name
126
+ self._select_model()
127
+
128
+ @on(Button.Pressed, "#select")
129
+ def _on_select_pressed(self) -> None:
130
+ self._select_model()
131
+
132
+ @on(Button.Pressed, "#done")
133
+ def _on_done_pressed(self) -> None:
134
+ self.action_done()
135
+
136
+ @property
137
+ def config_manager(self) -> ConfigManager:
138
+ app = cast("ShotgunApp", self.app)
139
+ return app.config_manager
140
+
141
+ def refresh_model_labels(self) -> None:
142
+ """Update the list view entries to reflect current selection."""
143
+ current_model = (
144
+ self.config_manager.load().selected_model or ModelName.CLAUDE_OPUS_4_1
145
+ )
146
+ for model_name in AVAILABLE_MODELS:
147
+ label = self.query_one(
148
+ f"#label-{_sanitize_model_name_for_id(model_name)}", Label
149
+ )
150
+ label.update(
151
+ self._model_label(model_name, is_current=model_name == current_model)
152
+ )
153
+
154
+ def _build_model_items(self) -> list[ListItem]:
155
+ items: list[ListItem] = []
156
+ current_model = self.selected_model
157
+ for model_name in AVAILABLE_MODELS:
158
+ label = Label(
159
+ self._model_label(model_name, is_current=model_name == current_model),
160
+ id=f"label-{_sanitize_model_name_for_id(model_name)}",
161
+ )
162
+ items.append(
163
+ ListItem(label, id=f"model-{_sanitize_model_name_for_id(model_name)}")
164
+ )
165
+ return items
166
+
167
+ def _model_from_item(self, item: ListItem | None) -> ModelName | None:
168
+ if item is None or item.id is None:
169
+ return None
170
+ sanitized_id = item.id.removeprefix("model-")
171
+ # Find the original model name by comparing sanitized versions
172
+ for model_name in AVAILABLE_MODELS:
173
+ if _sanitize_model_name_for_id(model_name) == sanitized_id:
174
+ return model_name
175
+ return None
176
+
177
+ def _model_label(self, model_name: ModelName, is_current: bool) -> str:
178
+ """Generate label for model with specs and current indicator."""
179
+ if model_name not in MODEL_SPECS:
180
+ return model_name.value
181
+
182
+ spec = MODEL_SPECS[model_name]
183
+ display_name = self._model_display_name(model_name)
184
+
185
+ # Format context/output tokens in readable format
186
+ input_k = spec.max_input_tokens // 1000
187
+ output_k = spec.max_output_tokens // 1000
188
+
189
+ label = f"{display_name} · {input_k}K context · {output_k}K output"
190
+
191
+ if is_current:
192
+ label += " · Current"
193
+
194
+ return label
195
+
196
+ def _model_display_name(self, model_name: ModelName) -> str:
197
+ """Get human-readable model name."""
198
+ names = {
199
+ ModelName.GPT_5: "GPT-5 (OpenAI)",
200
+ ModelName.CLAUDE_OPUS_4_1: "Claude Opus 4.1 (Anthropic)",
201
+ ModelName.GEMINI_2_5_PRO: "Gemini 2.5 Pro (Google)",
202
+ }
203
+ return names.get(model_name, model_name.value)
204
+
205
+ def _select_model(self) -> None:
206
+ """Save the selected model."""
207
+ try:
208
+ self.config_manager.update_selected_model(self.selected_model)
209
+ self.refresh_model_labels()
210
+ self.notify(
211
+ f"Selected model: {self._model_display_name(self.selected_model)}"
212
+ )
213
+ except Exception as exc: # pragma: no cover - defensive; textual path
214
+ self.notify(f"Failed to select model: {exc}", severity="error")
@@ -16,6 +16,9 @@ from shotgun.agents.config import ConfigManager, ProviderType
16
16
  if TYPE_CHECKING:
17
17
  from ..app import ShotgunApp
18
18
 
19
+ # Provider identifiers for configuration screen (LLM providers + Shotgun Account)
20
+ CONFIGURABLE_PROVIDERS = ["openai", "anthropic", "google", "shotgun"]
21
+
19
22
 
20
23
  class ProviderConfigScreen(Screen[None]):
21
24
  """Collect API keys for available providers."""
@@ -69,7 +72,7 @@ class ProviderConfigScreen(Screen[None]):
69
72
  ("escape", "done", "Back"),
70
73
  ]
71
74
 
72
- selected_provider: reactive[ProviderType] = reactive(ProviderType.OPENAI)
75
+ selected_provider: reactive[str] = reactive("openai")
73
76
 
74
77
  def compose(self) -> ComposeResult:
75
78
  with Vertical(id="titlebox"):
@@ -94,7 +97,7 @@ class ProviderConfigScreen(Screen[None]):
94
97
  list_view = self.query_one(ListView)
95
98
  if list_view.children:
96
99
  list_view.index = 0
97
- self.selected_provider = ProviderType.OPENAI
100
+ self.selected_provider = "openai"
98
101
  self.set_focus(self.query_one("#api-key", Input))
99
102
 
100
103
  def action_done(self) -> None:
@@ -144,45 +147,55 @@ class ProviderConfigScreen(Screen[None]):
144
147
 
145
148
  def refresh_provider_status(self) -> None:
146
149
  """Update the list view entries to reflect configured providers."""
147
- for provider in ProviderType:
148
- label = self.query_one(f"#label-{provider.value}", Label)
149
- label.update(self._provider_label(provider))
150
+ for provider_id in CONFIGURABLE_PROVIDERS:
151
+ label = self.query_one(f"#label-{provider_id}", Label)
152
+ label.update(self._provider_label(provider_id))
150
153
 
151
154
  def _build_provider_items(self) -> list[ListItem]:
152
155
  items: list[ListItem] = []
153
- for provider in ProviderType:
154
- label = Label(self._provider_label(provider), id=f"label-{provider.value}")
155
- items.append(ListItem(label, id=f"provider-{provider.value}"))
156
+ for provider_id in CONFIGURABLE_PROVIDERS:
157
+ label = Label(self._provider_label(provider_id), id=f"label-{provider_id}")
158
+ items.append(ListItem(label, id=f"provider-{provider_id}"))
156
159
  return items
157
160
 
158
- def _provider_from_item(self, item: ListItem | None) -> ProviderType | None:
161
+ def _provider_from_item(self, item: ListItem | None) -> str | None:
159
162
  if item is None or item.id is None:
160
163
  return None
161
164
  provider_id = item.id.removeprefix("provider-")
162
- try:
163
- return ProviderType(provider_id)
164
- except ValueError:
165
- return None
165
+ return provider_id if provider_id in CONFIGURABLE_PROVIDERS else None
166
166
 
167
- def _provider_label(self, provider: ProviderType) -> str:
168
- display = self._provider_display_name(provider)
167
+ def _provider_label(self, provider_id: str) -> str:
168
+ display = self._provider_display_name(provider_id)
169
169
  status = (
170
- "Configured"
171
- if self.config_manager.has_provider_key(provider)
172
- else "Not configured"
170
+ "Configured" if self._has_provider_key(provider_id) else "Not configured"
173
171
  )
174
172
  return f"{display} · {status}"
175
173
 
176
- def _provider_display_name(self, provider: ProviderType) -> str:
174
+ def _provider_display_name(self, provider_id: str) -> str:
177
175
  names = {
178
- ProviderType.OPENAI: "OpenAI",
179
- ProviderType.ANTHROPIC: "Anthropic",
180
- ProviderType.GOOGLE: "Google Gemini",
176
+ "openai": "OpenAI",
177
+ "anthropic": "Anthropic",
178
+ "google": "Google Gemini",
179
+ "shotgun": "Shotgun Account",
181
180
  }
182
- return names.get(provider, provider.value.title())
183
-
184
- def _input_placeholder(self, provider: ProviderType) -> str:
185
- return f"{self._provider_display_name(provider)} API key"
181
+ return names.get(provider_id, provider_id.title())
182
+
183
+ def _input_placeholder(self, provider_id: str) -> str:
184
+ return f"{self._provider_display_name(provider_id)} API key"
185
+
186
+ def _has_provider_key(self, provider_id: str) -> bool:
187
+ """Check if provider has a configured API key."""
188
+ if provider_id == "shotgun":
189
+ # Check shotgun key directly
190
+ config = self.config_manager.load()
191
+ return self.config_manager._provider_has_api_key(config.shotgun)
192
+ else:
193
+ # Check LLM provider key
194
+ try:
195
+ provider = ProviderType(provider_id)
196
+ return self.config_manager.has_provider_key(provider)
197
+ except ValueError:
198
+ return False
186
199
 
187
200
  def _save_api_key(self) -> None:
188
201
  input_widget = self.query_one("#api-key", Input)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shotgun-sh
3
- Version: 0.1.15.dev1
3
+ Version: 0.2.1.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
@@ -22,7 +22,6 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Classifier: Topic :: Utilities
23
23
  Requires-Python: >=3.11
24
24
  Requires-Dist: anthropic>=0.39.0
25
- Requires-Dist: google-generativeai>=0.8.5
26
25
  Requires-Dist: httpx>=0.27.0
27
26
  Requires-Dist: jinja2>=3.1.0
28
27
  Requires-Dist: kuzu>=0.7.0
@@ -32,6 +31,7 @@ Requires-Dist: packaging>=23.0
32
31
  Requires-Dist: posthog>=3.0.0
33
32
  Requires-Dist: pydantic-ai>=0.0.14
34
33
  Requires-Dist: rich>=13.0.0
34
+ Requires-Dist: sentencepiece>=0.2.0
35
35
  Requires-Dist: sentry-sdk[pure-eval]>=2.0.0
36
36
  Requires-Dist: textual-dev>=1.7.0
37
37
  Requires-Dist: textual>=6.1.0
@@ -1,37 +1,44 @@
1
1
  shotgun/__init__.py,sha256=P40K0fnIsb7SKcQrFnXZ4aREjpWchVDhvM1HxI4cyIQ,104
2
2
  shotgun/build_constants.py,sha256=RXNxMz46HaB5jucgMVpw8a2yCJqjbhTOh0PddyEVMN8,713
3
3
  shotgun/logging_config.py,sha256=UKenihvgH8OA3W0b8ZFcItYaFJVe9MlsMYlcevyW1HY,7440
4
- shotgun/main.py,sha256=670RwzIwEIz9QRil37IbVoxWuX66YATqXFLSYSqKw-w,4955
5
- shotgun/posthog_telemetry.py,sha256=ZD_BjRej1v4Mxh7VN3AlXGKV4jIU9SC0uBrH94VQa6c,5885
4
+ shotgun/main.py,sha256=RA3q1xPfqxCu43UmgI2ryZpA-IxPhJb_MJrbLqp9c_g,5140
5
+ shotgun/posthog_telemetry.py,sha256=RGA_rgKxAnIofjkm-cLKzyuckAKz-861gpp97tk8IME,5949
6
6
  shotgun/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  shotgun/sentry_telemetry.py,sha256=L7jFMNAnDIENWVeQYSLpyul2nmIm2w3wnOp2kDP_cic,2902
8
8
  shotgun/telemetry.py,sha256=Ves6Ih3hshpKVNVAUUmwRdtW8NkTjFPg8hEqvFKZ0t0,3208
9
9
  shotgun/agents/__init__.py,sha256=8Jzv1YsDuLyNPFJyckSr_qI4ehTVeDyIMDW4omsfPGc,25
10
10
  shotgun/agents/agent_manager.py,sha256=wXUQCEsSs68FG8edFLryeePBzxxX1GStJZwd1sS5WsE,26245
11
- shotgun/agents/common.py,sha256=vt7ECq1rT6GR5Rt63t0whH0R0cydrk7Mty2KyPL8mEg,19045
11
+ shotgun/agents/common.py,sha256=Hr9HigsDopkI0Sr3FThGDv1f67NLemOjcYA6LV9v970,18963
12
12
  shotgun/agents/conversation_history.py,sha256=5J8_1yxdZiiWTq22aDio88DkBDZ4_Lh_p5Iy5_ENszc,3898
13
13
  shotgun/agents/conversation_manager.py,sha256=fxAvXbEl3Cl2ugJ4N9aWXaqZtkrnfj3QzwjWC4LFXwI,3514
14
14
  shotgun/agents/export.py,sha256=Zke952DbJ_lOBUmN-TPHw7qmjbfqsFu1uycBRQI_pkg,2969
15
+ shotgun/agents/llm.py,sha256=hs8j1wwTczGtehzahL1Z_5D4qus5QUx4-h9-m5ZPzm4,2209
15
16
  shotgun/agents/messages.py,sha256=wNn0qC5AqASM8LMaSGFOerZEJPn5FsIOmaJs1bdosuU,1036
16
- shotgun/agents/models.py,sha256=fljmjHoCzNXPWOHSA-1KmQk1epk8ovowqDM7j5zZKB8,7853
17
+ shotgun/agents/models.py,sha256=n4N141QOPmcuFjJkn5uZRAvtVwF1acsAJE8QlQABCiM,7845
17
18
  shotgun/agents/plan.py,sha256=s-WfILBOW4l8kY59RUOVtX5MJSuSzFm1nGp6b17If78,3030
18
19
  shotgun/agents/research.py,sha256=lYG7Rytcitop8mXs3isMI3XvYzzI3JH9u0VZz6K9zfo,3274
19
20
  shotgun/agents/specify.py,sha256=7MoMxfIn34G27mw6wrp_F0i2O5rid476L3kHFONDCd0,3137
20
21
  shotgun/agents/tasks.py,sha256=nk8zIl24o01hfzOGyWSbeVWeke6OGseO4Ppciurh13U,2999
21
22
  shotgun/agents/config/__init__.py,sha256=Fl8K_81zBpm-OfOW27M_WWLSFdaHHek6lWz95iDREjQ,318
22
- shotgun/agents/config/constants.py,sha256=MogArrb2r5rFI6BBzc6NhPz1payGeM6K-t5oIFbJgxg,494
23
- shotgun/agents/config/manager.py,sha256=kwMbPjz0kEH_WCQAamESGjHdE8d_P-ztel4NL4FWNUw,10662
24
- shotgun/agents/config/models.py,sha256=vpVXrtiHsDt2D_h7BLyMiiQeT97vAz2L6lYKx2SEMjo,5909
25
- shotgun/agents/config/provider.py,sha256=pVWf_WM3MNWH0v2fU-peBCqx49X-nW81piQ_M-AKWRE,7249
23
+ shotgun/agents/config/constants.py,sha256=I3f0ueoQaTg5HddXGCYimCYpj-U57z3IBQYIVJxVIhg,872
24
+ shotgun/agents/config/manager.py,sha256=phm_oqObIrCGJrZUvVbwSJHB--Mn7zqJLWB9ZWok5lY,15042
25
+ shotgun/agents/config/models.py,sha256=h1XqPOh66moIYaXtEyoGJuPLXdD3acVCOgvgrELsS_4,4796
26
+ shotgun/agents/config/provider.py,sha256=V4s7HwU3XwCWqmvMPoDiG9pVjUuuyNWidvqhImLXvxE,11547
26
27
  shotgun/agents/history/__init__.py,sha256=XFQj2a6fxDqVg0Q3juvN9RjV_RJbgvFZtQOCOjVJyp4,147
27
- shotgun/agents/history/compaction.py,sha256=Je8-7T2i78gv_QWzgZNe9mvscaHcaTMttQX9xS8M38Q,3509
28
+ shotgun/agents/history/compaction.py,sha256=9RMpG0aY_7L4TecbgwHSOkGtbd9W5XZTg-MbzZmNl00,3515
28
29
  shotgun/agents/history/constants.py,sha256=yWY8rrTZarLA3flCCMB_hS2NMvUDRDTwP4D4j7MIh1w,446
29
30
  shotgun/agents/history/context_extraction.py,sha256=yVka1U6TqNVsORR4JlxpWi9yBt3Quip8g_u3x2Vi9Gs,3564
30
31
  shotgun/agents/history/history_building.py,sha256=6LFDZ60MTPDoGAcmu_mjlnjVYu8YYWdIi-cGbF3jm7A,3532
31
- shotgun/agents/history/history_processors.py,sha256=NbStr6CvszwK3DKO5LCiaVEJI-RAcVnH5dCpHTAHjQo,17731
32
+ shotgun/agents/history/history_processors.py,sha256=D3z-hzrXHxE7OAZaVX4_YAKN_nyxSF5iYMIYO24V_CI,17943
32
33
  shotgun/agents/history/message_utils.py,sha256=aPusAl2RYKbjc7lBxPaNprRHmZEG6fe97q7DQUlhlzU,2918
33
- shotgun/agents/history/token_counting.py,sha256=RasWy84eNjbmqyQDTGAzj1Q1I9ml_G_9R-maWN7gr8s,13839
34
- shotgun/agents/history/token_estimation.py,sha256=iNqhDSqFzG0YYxGijMRzj54GALFglOp0qVMB6G59RhU,4690
34
+ shotgun/agents/history/token_estimation.py,sha256=iRyKq-YDivEpJrULIbQgNpjhOuSC4nHVJYfsWEFV8sQ,4770
35
+ shotgun/agents/history/token_counting/__init__.py,sha256=YZt5Lus--fkF6l1hdkIlp1e_oAIpACNwHOI0FRP4q8s,924
36
+ shotgun/agents/history/token_counting/anthropic.py,sha256=b2LvwKM4dSILGhv_-W4mLMKMUCPLhe1ov9UGW_-iBsw,3011
37
+ shotgun/agents/history/token_counting/base.py,sha256=TN4mzwSyWNQyTuOuCFaU-8AgLdAyquoX3af4qrmkxCs,1904
38
+ shotgun/agents/history/token_counting/openai.py,sha256=XJ2z2HaUG6f3Cw9tCK_yaOsaMJGHpSFF1I30-d3soSI,2350
39
+ shotgun/agents/history/token_counting/sentencepiece_counter.py,sha256=qj1bT7J5nCd5y6Mr42O9K1KTaele0rjdd09FeyyEA70,3987
40
+ shotgun/agents/history/token_counting/tokenizer_cache.py,sha256=Y0V6KMtEwn42M5-zJGAc7YudM8X6m5-j2ekA6YGL5Xk,2868
41
+ shotgun/agents/history/token_counting/utils.py,sha256=d124IDjtd0IYBYrr3gDJGWxSbdP10Vrc7ZistbUosMg,5002
35
42
  shotgun/agents/tools/__init__.py,sha256=QaN80IqWvB5qEcjHqri1-PYvYlO74vdhcwLugoEdblo,772
36
43
  shotgun/agents/tools/file_management.py,sha256=HYNe_QA4T3_bPzSWBYcFZcnWdj8eb4aQ3GB735-G8Nw,7138
37
44
  shotgun/agents/tools/user_interaction.py,sha256=b3ncEpvoD06Cz4hwsS-ppVbQajQj640iWnVfA5WBjAA,1236
@@ -42,16 +49,16 @@ shotgun/agents/tools/codebase/file_read.py,sha256=EGK5yNqiS4cbIEQfDtdKVoJSJYk20N
42
49
  shotgun/agents/tools/codebase/models.py,sha256=8eR3_8DQiBNgB2twu0aC_evIJbugN9KW3gtxMZdGYCE,10087
43
50
  shotgun/agents/tools/codebase/query_graph.py,sha256=vOeyN4-OZj-vpTSk3Z9W5TjraZAepJ-Qjk_zzvum3fU,2115
44
51
  shotgun/agents/tools/codebase/retrieve_code.py,sha256=2VjiqVKJMd9rPV-mGrL4C-N8fqGjYLW6ZInFGbcTxOM,2878
45
- shotgun/agents/tools/web_search/__init__.py,sha256=Sj1tVokrCsJiLRWWTq0zrAolMHEGntRIYnqiyFi8L2E,1840
46
- shotgun/agents/tools/web_search/anthropic.py,sha256=NDhj8MrdxLsmGwHp7uM0IQeJVW2poY58GCUTJEM9dew,4827
47
- shotgun/agents/tools/web_search/gemini.py,sha256=hXjWUF-aTX3B9ViaKe5aF2aHXlaoBA5am40cgilinGE,2981
48
- shotgun/agents/tools/web_search/openai.py,sha256=V8GeqwUAi5wrbRuU41Y38schpXRdyeIfw85-CT5rAhY,3415
52
+ shotgun/agents/tools/web_search/__init__.py,sha256=_9rgs_gv41-wfPvwfWM_Qfq-zvboyQ_srfyneGsxgM4,3182
53
+ shotgun/agents/tools/web_search/anthropic.py,sha256=wN3dRBXohIwcJRp0KA3QTgldGjKuDZ2NW4X36mvIn3E,4971
54
+ shotgun/agents/tools/web_search/gemini.py,sha256=-fI_deaBT4-_61A7KlKtz8tmKXW50fVx_97WAJTUg4w,3468
55
+ shotgun/agents/tools/web_search/openai.py,sha256=pnIcTV3vwXJQuxPs4I7gQNX18XzM7D7FqeNxnn1E7yw,3437
49
56
  shotgun/agents/tools/web_search/utils.py,sha256=GLJ5QV9bT2ubFMuFN7caMN7tK9OTJ0R3GD57B-tCMF0,532
50
57
  shotgun/cli/__init__.py,sha256=_F1uW2g87y4bGFxz8Gp8u7mq2voHp8vQIUtCmm8Tojo,40
51
- shotgun/cli/config.py,sha256=LbjxDNPdetYJiwlcyOYLnqwzALfgU-m54cfstUshbrs,8715
58
+ shotgun/cli/config.py,sha256=wQhuz8zE2K-fjwxeK2yZt-NkV13kEZAitBqrwPLUvgg,7466
52
59
  shotgun/cli/export.py,sha256=3hIwK2_OM1MFYSTfzBxsGuuBGm5fo0XdxASfQ5Uqb3Y,2471
53
60
  shotgun/cli/feedback.py,sha256=Sh0aK93wE7rvvCI31QCbm0sU-AUEldg7s9QqoAm1oQM,1242
54
- shotgun/cli/models.py,sha256=LoajeEK7MEDUSnZXb1Li-dbhXqne812YZglx-LcVpiQ,181
61
+ shotgun/cli/models.py,sha256=kwZEldQWUheNsqF_ezgDzRBc6h0Y0JxFw1VMQjZlvPE,182
55
62
  shotgun/cli/plan.py,sha256=T-eu-I9z-dSoKqJ-KI8X5i5Mm0VL1BfornxRiUjTgnk,2324
56
63
  shotgun/cli/research.py,sha256=qvBBtX3Wyn6pDZlJpcEvbeK-0iTOXegi71tm8HKVYaE,2490
57
64
  shotgun/cli/specify.py,sha256=ErRQ72Zc75fmxopZbKy0vvnLPuYBLsGynpjj1X6-BwI,2166
@@ -62,7 +69,7 @@ shotgun/cli/codebase/__init__.py,sha256=rKdvx33p0i_BYbNkz5_4DCFgEMwzOOqLi9f5p7XT
62
69
  shotgun/cli/codebase/commands.py,sha256=1N2yOGmok0ZarqXPIpWGcsQrwm_ZJcyWiMxy6tm0j70,8711
63
70
  shotgun/cli/codebase/models.py,sha256=B9vs-d-Bq0aS6FZKebhHT-9tw90Y5f6k_t71VlZpL8k,374
64
71
  shotgun/codebase/__init__.py,sha256=QBgFE2Abd5Vl7_NdYOglF9S6d-vIjkb3C0cpIYoHZEU,309
65
- shotgun/codebase/models.py,sha256=1AAipm6KrGOHmYBBavugnyeOsVkzX-YXAD6dDsSVRWg,5299
72
+ shotgun/codebase/models.py,sha256=5e_7zaPL032n_ghcvs01Uug3BH4jyKiQ3S3U5w21BSM,5296
66
73
  shotgun/codebase/service.py,sha256=nyggapfHKdwkKXyuT9oA0tJ9qf4RNVsOxfY8lC5pHro,8006
67
74
  shotgun/codebase/core/__init__.py,sha256=GWWhJEqChiDXAF4omYCgzgoZmJjwsAf6P1aZ5Bl8OE0,1170
68
75
  shotgun/codebase/core/change_detector.py,sha256=kWCYLWzRzb3IGGOj71KBn7UOCOKMpINJbOBDf98aMxE,12409
@@ -73,6 +80,9 @@ shotgun/codebase/core/language_config.py,sha256=vsqHyuFnumRPRBV1lMOxWKNOIiClO6Fy
73
80
  shotgun/codebase/core/manager.py,sha256=USGLBdDUoFtq6fMFWRtUu2HBC_FI8d6lWcAV4l6fcvk,66000
74
81
  shotgun/codebase/core/nl_query.py,sha256=kPoSJXBlm5rLhzOofZhqPVMJ_Lj3rV2H6sld6BwtMdg,16115
75
82
  shotgun/codebase/core/parser_loader.py,sha256=LZRrDS8Sp518jIu3tQW-BxdwJ86lnsTteI478ER9Td8,4278
83
+ shotgun/llm_proxy/__init__.py,sha256=BLD9NnVzdD0H7gFb65Ajud-Q7SiCymegLRaGx8UkC-Y,435
84
+ shotgun/llm_proxy/clients.py,sha256=wP4UlgtCdrNwWsZLZ9inE3fEIDa-i1j7gsr9oXQf1o4,1037
85
+ shotgun/llm_proxy/constants.py,sha256=E8sqL-8GZzl989T3OS7E1hImSZPj2vqmp3lbM6zGiQU,309
76
86
  shotgun/prompts/__init__.py,sha256=RswUm0HMdfm2m2YKUwUsEdRIwoczdbI7zlucoEvHYRo,132
77
87
  shotgun/prompts/loader.py,sha256=jy24-E02pCSmz2651aCT2NgHfRrHAGMYvKrD6gs0Er8,4424
78
88
  shotgun/prompts/agents/__init__.py,sha256=YRIJMbzpArojNX1BP5gfxxois334z_GQga8T-xyWMbY,39
@@ -103,7 +113,7 @@ shotgun/sdk/exceptions.py,sha256=qBcQv0v7ZTwP7CMcxZST4GqCsfOWtOUjSzGBo0-heqo,412
103
113
  shotgun/sdk/models.py,sha256=X9nOTUHH0cdkQW1NfnMEDu-QgK9oUsEISh1Jtwr5Am4,5496
104
114
  shotgun/sdk/services.py,sha256=J4PJFSxCQ6--u7rb3Ta-9eYtlYcxcbnzrMP6ThyCnw4,705
105
115
  shotgun/tui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
- shotgun/tui/app.py,sha256=HAfPbTSS8oyWlqoGL5hYw356_nHEGxHWrERdIA0uh2Q,4998
116
+ shotgun/tui/app.py,sha256=Rv4Pxi2uyDE_tspZGMWKJY1KrH47d8uCIBBMfM05gCQ,5093
107
117
  shotgun/tui/filtered_codebase_service.py,sha256=lJ8gTMhIveTatmvmGLP299msWWTkVYKwvY_2FhuL2s4,1687
108
118
  shotgun/tui/styles.tcss,sha256=ETyyw1bpMBOqTi5RLcAJUScdPWTvAWEqE9YcT0kVs_E,121
109
119
  shotgun/tui/commands/__init__.py,sha256=8D5lvtpqMW5-fF7Bg3oJtUzU75cKOv6aUaHYYszydU8,2518
@@ -115,10 +125,11 @@ shotgun/tui/screens/chat.py,sha256=HIDnqt8og2KMmtdOok1lL44130M8V7IP6Un_8HcRwsA,3
115
125
  shotgun/tui/screens/chat.tcss,sha256=2Yq3E23jxsySYsgZf4G1AYrYVcpX0UDW6kNNI0tDmtM,437
116
126
  shotgun/tui/screens/directory_setup.py,sha256=lIZ1J4A6g5Q2ZBX8epW7BhR96Dmdcg22CyiM5S-I5WU,3237
117
127
  shotgun/tui/screens/feedback.py,sha256=cYtmuM3qqKwevstu8gJ9mmk7lkIKZvfAyDEBUOLh-yI,5660
118
- shotgun/tui/screens/provider_config.py,sha256=A_tvDHF5KLP5PV60LjMJ_aoOdT3TjI6_g04UIUqGPqM,7126
128
+ shotgun/tui/screens/model_picker.py,sha256=2l0zkhJ5CPH_4Fn0MM3bp9RN7fEowbljpBsmTjzRQT8,6886
129
+ shotgun/tui/screens/provider_config.py,sha256=-en99fDxTim0DSjpJTLSRba_yrON8wDhcuwU6rNZwHM,7765
119
130
  shotgun/tui/screens/splash.py,sha256=E2MsJihi3c9NY1L28o_MstDxGwrCnnV7zdq00MrGAsw,706
120
131
  shotgun/tui/screens/chat_screen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
- shotgun/tui/screens/chat_screen/command_providers.py,sha256=55JIH9T8QnyHRsMoXhOi87FiVM-d6o7OKpCe82uDP9I,7840
132
+ shotgun/tui/screens/chat_screen/command_providers.py,sha256=B4uUzzGq23vfS1mp4U6zsOEqyv6Ni9AMu5fqp5xMz5s,8437
122
133
  shotgun/tui/screens/chat_screen/hint_message.py,sha256=WOpbk8q7qt7eOHTyyHvh_IQIaublVDeJGaLpsxEk9FA,933
123
134
  shotgun/tui/screens/chat_screen/history.py,sha256=NVLA3_tERTyB4vkH71w8ef_M5CszfkwbQOuMb100Fzc,12272
124
135
  shotgun/tui/utils/__init__.py,sha256=cFjDfoXTRBq29wgP7TGRWUu1eFfiIG-LLOzjIGfadgI,150
@@ -128,8 +139,8 @@ shotgun/utils/env_utils.py,sha256=8QK5aw_f_V2AVTleQQlcL0RnD4sPJWXlDG46fsHu0d8,10
128
139
  shotgun/utils/file_system_utils.py,sha256=l-0p1bEHF34OU19MahnRFdClHufThfGAjQ431teAIp0,1004
129
140
  shotgun/utils/source_detection.py,sha256=Co6Q03R3fT771TF3RzB-70stfjNP2S4F_ArZKibwzm8,454
130
141
  shotgun/utils/update_checker.py,sha256=IgzPHRhS1ETH7PnJR_dIx6lxgr1qHpCkMTgzUxvGjhI,7586
131
- shotgun_sh-0.1.15.dev1.dist-info/METADATA,sha256=EeBReM7IB4Iw_Nf9bkzFAkQL0LPGZzILv3N_A77FRqk,11197
132
- shotgun_sh-0.1.15.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
133
- shotgun_sh-0.1.15.dev1.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
134
- shotgun_sh-0.1.15.dev1.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
135
- shotgun_sh-0.1.15.dev1.dist-info/RECORD,,
142
+ shotgun_sh-0.2.1.dev1.dist-info/METADATA,sha256=KnWsl_ASqmh5tc4yblK9TGGltQxztoW_XYK7fNPCLqE,11190
143
+ shotgun_sh-0.2.1.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
144
+ shotgun_sh-0.2.1.dev1.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
145
+ shotgun_sh-0.2.1.dev1.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
146
+ shotgun_sh-0.2.1.dev1.dist-info/RECORD,,