shotgun-sh 0.2.5__py3-none-any.whl → 0.2.6__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.

@@ -19,7 +19,6 @@ from textual.reactive import reactive
19
19
  from textual.widget import Widget
20
20
  from textual.widgets import Markdown
21
21
 
22
- from shotgun.agents.models import UserAnswer
23
22
  from shotgun.tui.components.vertical_tail import VerticalTail
24
23
  from shotgun.tui.screens.chat_screen.hint_message import HintMessage, HintMessageWidget
25
24
 
@@ -103,42 +102,8 @@ class ChatHistory(Widget):
103
102
  self._rendered_count = len(filtered)
104
103
 
105
104
  def filtered_items(self) -> Generator[ModelMessage | HintMessage, None, None]:
106
- for idx, next_item in enumerate(self.items):
107
- prev_item = self.items[idx - 1] if idx > 0 else None
108
-
109
- if isinstance(prev_item, ModelRequest) and isinstance(
110
- next_item, ModelResponse
111
- ):
112
- ask_user_tool_response_part = next(
113
- (
114
- part
115
- for part in prev_item.parts
116
- if isinstance(part, ToolReturnPart)
117
- and part.tool_name == "ask_user"
118
- ),
119
- None,
120
- )
121
-
122
- ask_user_part = next(
123
- (
124
- part
125
- for part in next_item.parts
126
- if isinstance(part, ToolCallPart)
127
- and part.tool_name == "ask_user"
128
- ),
129
- None,
130
- )
131
-
132
- if not ask_user_part or not ask_user_tool_response_part:
133
- yield next_item
134
- continue
135
- if (
136
- ask_user_tool_response_part.tool_call_id
137
- == ask_user_part.tool_call_id
138
- ):
139
- continue # don't emit tool call that happens after tool response
140
-
141
- yield next_item
105
+ # Simply yield all items - no filtering needed now that ask_user/ask_questions are gone
106
+ yield from self.items
142
107
 
143
108
  def update_messages(self, messages: list[ModelMessage | HintMessage]) -> None:
144
109
  """Update the displayed messages using incremental mounting."""
@@ -167,6 +132,9 @@ class ChatHistory(Widget):
167
132
 
168
133
  self._rendered_count = len(filtered)
169
134
 
135
+ # Scroll to bottom to show newly added messages
136
+ self.vertical_tail.scroll_end(animate=False)
137
+
170
138
 
171
139
  class UserQuestionWidget(Widget):
172
140
  def __init__(self, item: ModelRequest | None) -> None:
@@ -189,13 +157,8 @@ class UserQuestionWidget(Widget):
189
157
  f"**>** {part.content if isinstance(part.content, str) else ''}\n\n"
190
158
  )
191
159
  elif isinstance(part, ToolReturnPart):
192
- if part.tool_name == "ask_user":
193
- acc += f"**>** {part.content.answer if isinstance(part.content, UserAnswer) else part.content['answer']}\n\n"
194
- else:
195
- # acc += " ∟ finished\n\n" # let's not show anything yet
196
- pass
197
- elif isinstance(part, UserPromptPart):
198
- acc += f"**>** {part.content}\n\n"
160
+ # Don't show tool return parts in the UI
161
+ pass
199
162
  return acc
200
163
 
201
164
 
@@ -215,6 +178,7 @@ class AgentResponseWidget(Widget):
215
178
  acc = ""
216
179
  if self.item is None:
217
180
  return ""
181
+
218
182
  for idx, part in enumerate(self.item.parts):
219
183
  if isinstance(part, TextPart):
220
184
  # Only show the circle prefix if there's actual content
@@ -222,9 +186,28 @@ class AgentResponseWidget(Widget):
222
186
  acc += f"**⏺** {part.content}\n\n"
223
187
  elif isinstance(part, ToolCallPart):
224
188
  parts_str = self._format_tool_call_part(part)
225
- acc += parts_str + "\n\n"
189
+ if parts_str: # Only add if there's actual content
190
+ acc += parts_str + "\n\n"
226
191
  elif isinstance(part, BuiltinToolCallPart):
227
- acc += f"{part.tool_name}({part.args})\n\n"
192
+ # Format builtin tool calls better
193
+ if part.tool_name and "search" in part.tool_name.lower():
194
+ args = self._parse_args(part.args)
195
+ if isinstance(args, dict) and "query" in args:
196
+ query = self._truncate(str(args.get("query", "")))
197
+ acc += f'Searching: "{query}"\n\n'
198
+ else:
199
+ acc += f"{part.tool_name}()\n\n"
200
+ else:
201
+ # For other builtin tools, show name only or with truncated args
202
+ if part.args:
203
+ args_str = (
204
+ str(part.args)[:50] + "..."
205
+ if len(str(part.args)) > 50
206
+ else str(part.args)
207
+ )
208
+ acc += f"{part.tool_name}({args_str})\n\n"
209
+ else:
210
+ acc += f"{part.tool_name}()\n\n"
228
211
  elif isinstance(part, BuiltinToolReturnPart):
229
212
  acc += f"builtin tool ({part.tool_name}) return: {part.content}\n\n"
230
213
  elif isinstance(part, ThinkingPart):
@@ -258,9 +241,6 @@ class AgentResponseWidget(Widget):
258
241
  return args if isinstance(args, dict) else {}
259
242
 
260
243
  def _format_tool_call_part(self, part: ToolCallPart) -> str:
261
- if part.tool_name == "ask_user":
262
- return self._format_ask_user_part(part)
263
-
264
244
  # Parse args once (handles both JSON string and dict)
265
245
  args = self._parse_args(part.args)
266
246
 
@@ -305,12 +285,16 @@ class AgentResponseWidget(Widget):
305
285
  return f'Reading file: "{args["filename"]}"'
306
286
  return "Reading file"
307
287
 
308
- # Web search tools
309
- if part.tool_name in [
310
- "openai_web_search_tool",
311
- "anthropic_web_search_tool",
312
- "gemini_web_search_tool",
313
- ]:
288
+ # Web search tools - handle variations
289
+ if (
290
+ part.tool_name
291
+ in [
292
+ "openai_web_search_tool",
293
+ "anthropic_web_search_tool",
294
+ "gemini_web_search_tool",
295
+ ]
296
+ or "search" in part.tool_name.lower()
297
+ ): # Catch other search variations
314
298
  if "query" in args:
315
299
  query = self._truncate(str(args["query"]))
316
300
  return f'Searching web: "{query}"'
@@ -327,26 +311,25 @@ class AgentResponseWidget(Widget):
327
311
  return f"{part.tool_name}({args['section_title']})"
328
312
  return f"{part.tool_name}()"
329
313
 
330
- if part.tool_name == "create_artifact":
331
- if "name" in args:
332
- return f"{part.tool_name}({args['name']})"
333
- return f"▪ {part.tool_name}()"
334
-
335
- return f"{part.tool_name}({part.args})"
336
-
337
- def _format_ask_user_part(
338
- self,
339
- part: ToolCallPart,
340
- ) -> str:
341
- if isinstance(part.args, str):
342
- try:
343
- _args = json.loads(part.args) if part.args.strip() else {}
344
- except json.JSONDecodeError:
345
- _args = {}
346
- else:
347
- _args = part.args
314
+ if part.tool_name == "final_result":
315
+ # Hide final_result tool calls completely - they're internal Pydantic AI mechanics
316
+ return ""
348
317
 
349
- if isinstance(_args, dict) and "question" in _args:
350
- return f"{_args['question']}"
318
+ # Default case for unrecognized tools - format args properly
319
+ args = self._parse_args(part.args)
320
+ if args and isinstance(args, dict):
321
+ # Try to extract common fields
322
+ if "query" in args:
323
+ return f'{part.tool_name}: "{self._truncate(str(args["query"]))}"'
324
+ elif "question" in args:
325
+ return f'{part.tool_name}: "{self._truncate(str(args["question"]))}"'
326
+ else:
327
+ # Show tool name with truncated args
328
+ args_str = (
329
+ str(part.args)[:50] + "..."
330
+ if len(str(part.args)) > 50
331
+ else str(part.args)
332
+ )
333
+ return f"{part.tool_name}({args_str})"
351
334
  else:
352
- return ""
335
+ return f"{part.tool_name}()"
@@ -152,6 +152,10 @@ class WelcomeScreen(Screen[None]):
152
152
  @on(Button.Pressed, "#byok-button")
153
153
  def _on_byok_pressed(self) -> None:
154
154
  """Handle BYOK button press."""
155
+ self.run_worker(self._start_byok_config(), exclusive=True)
156
+
157
+ async def _start_byok_config(self) -> None:
158
+ """Launch BYOK provider configuration flow."""
155
159
  self._mark_welcome_shown()
156
160
 
157
161
  app = cast("ShotgunApp", self.app)
@@ -161,10 +165,14 @@ class WelcomeScreen(Screen[None]):
161
165
  self.dismiss()
162
166
  return
163
167
 
164
- # Otherwise, push provider config screen
168
+ # Otherwise, push provider config screen and wait for result
165
169
  from .provider_config import ProviderConfigScreen
166
170
 
167
- self.app.push_screen(ProviderConfigScreen())
171
+ await self.app.push_screen_wait(ProviderConfigScreen())
172
+
173
+ # Dismiss welcome screen after config if providers are now configured
174
+ if app.config_manager.has_any_provider_key():
175
+ self.dismiss()
168
176
 
169
177
  async def _start_shotgun_auth(self) -> None:
170
178
  """Launch Shotgun Account authentication flow."""
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: shotgun-sh
3
+ Version: 0.2.6
4
+ Summary: AI-powered research, planning, and task management CLI tool
5
+ Project-URL: Homepage, https://shotgun.sh/
6
+ Project-URL: Repository, https://github.com/shotgun-sh/shotgun
7
+ Project-URL: Issues, https://github.com/shotgun-sh/shotgun-alpha/issues
8
+ Project-URL: Discord, https://discord.gg/5RmY6J2N7s
9
+ Author-email: "Proofs.io" <hello@proofs.io>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,ai,cli,llm,planning,productivity,pydantic-ai,research,task-management
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: anthropic>=0.39.0
25
+ Requires-Dist: genai-prices>=0.0.27
26
+ Requires-Dist: httpx>=0.27.0
27
+ Requires-Dist: jinja2>=3.1.0
28
+ Requires-Dist: kuzu>=0.7.0
29
+ Requires-Dist: logfire[pydantic-ai]>=2.0.0
30
+ Requires-Dist: openai>=1.0.0
31
+ Requires-Dist: packaging>=23.0
32
+ Requires-Dist: posthog>=3.0.0
33
+ Requires-Dist: pydantic-ai>=0.0.14
34
+ Requires-Dist: rich>=13.0.0
35
+ Requires-Dist: sentencepiece>=0.2.0
36
+ Requires-Dist: sentry-sdk[pure-eval]>=2.0.0
37
+ Requires-Dist: textual-dev>=1.7.0
38
+ Requires-Dist: textual>=6.1.0
39
+ Requires-Dist: tiktoken>=0.7.0
40
+ Requires-Dist: tree-sitter-go>=0.23.0
41
+ Requires-Dist: tree-sitter-javascript>=0.23.0
42
+ Requires-Dist: tree-sitter-python>=0.23.0
43
+ Requires-Dist: tree-sitter-rust>=0.23.0
44
+ Requires-Dist: tree-sitter-typescript>=0.23.0
45
+ Requires-Dist: tree-sitter>=0.21.0
46
+ Requires-Dist: typer>=0.12.0
47
+ Requires-Dist: watchdog>=4.0.0
48
+ Provides-Extra: dev
49
+ Requires-Dist: commitizen>=3.13.0; extra == 'dev'
50
+ Requires-Dist: lefthook>=1.12.0; extra == 'dev'
51
+ Requires-Dist: mypy>=1.11.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # Shotgun
56
+
57
+ **Spec-Driven Development for AI Code Generation**
58
+
59
+ Shotgun is a CLI tool that turns work with AI code-gen tools from "I want to build X" into: **research → specs → plans → tasks → implementation**. It reads your entire codebase, coordinates AI agents to do the heavy lifting, and exports clean artifacts in the agents.md format so your code-gen tools actually know what they're building.
60
+
61
+ 🌐 **Learn more at [shotgun.sh](https://shotgun.sh/)**
62
+
63
+ ## Features
64
+
65
+ ### 📊 Complete Codebase Understanding
66
+
67
+ Before writing a single line, Shotgun reads all of it. Your patterns. Your dependencies. Your technical debt. Whether you're adding features, onboarding devs, planning migrations, or refactoring - Shotgun knows what you're working with.
68
+
69
+ ### 🔄 Five Modes. One Journey. Zero Gaps.
70
+
71
+ **Research** (what exists) → **Specify** (what to build) → **Plan** (how to build) → **Tasks** (break it down) → **Export** (to any tool)
72
+
73
+ Not another chatbot. A complete workflow where each mode feeds the next.
74
+
75
+ ### ➡️ Export to agents.md
76
+
77
+ Outputs plug into many code-generation tools including Codex, Cursor, Warp, Devin, opencode, Jules, and more.
78
+
79
+ ### 📝 Specs That Don't Die in Slack
80
+
81
+ Every research finding, every architectural decision, every "here's why we didn't use that library" - captured as markdown in your repo. Version controlled. Searchable.
82
+
83
+ ## Installation
84
+
85
+ ### Using pipx (Recommended)
86
+
87
+ ```bash
88
+ pipx install shotgun-sh
89
+ ```
90
+
91
+ **Why pipx?** It installs Shotgun in an isolated environment, preventing dependency conflicts with your other Python projects.
92
+
93
+ ### Using pip
94
+
95
+ ```bash
96
+ pip install shotgun-sh
97
+ ```
98
+
99
+ ## Quick Start
100
+
101
+ ```bash
102
+ # Research your codebase or a topic
103
+ shotgun research "What is our authentication flow?"
104
+
105
+ # Generate specifications
106
+ shotgun spec "Add OAuth2 authentication"
107
+
108
+ # Create an implementation plan
109
+ shotgun plan "Build user dashboard"
110
+
111
+ # Break down into tasks
112
+ shotgun tasks "Implement payment system"
113
+
114
+ # Export to agents.md format for your code-gen tools
115
+ shotgun export
116
+ ```
117
+
118
+ ## Support
119
+
120
+ Have questions? Join our community on **[Discord](https://discord.gg/5RmY6J2N7s)**
121
+
122
+ ---
123
+
124
+ **License:** MIT
125
+ **Python:** 3.11+
@@ -6,24 +6,24 @@ shotgun/main.py,sha256=RA3q1xPfqxCu43UmgI2ryZpA-IxPhJb_MJrbLqp9c_g,5140
6
6
  shotgun/posthog_telemetry.py,sha256=TOiyBtLg21SttHGWKc4-e-PQgpbq6Uz_4OzlvlxMcZ0,6099
7
7
  shotgun/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  shotgun/sentry_telemetry.py,sha256=VD8es-tREfgtRKhDsEVvqpo0_kM_ab6iVm2lkOEmTlI,2950
9
- shotgun/telemetry.py,sha256=WfxdHALh5_51nw783ZZvD-LEyC6ypHxSUTMXUioZhTQ,3339
9
+ shotgun/telemetry.py,sha256=C8dM7Feo1OxJMwDvgAMaA2RyRDO2rYPvC_8kLBuRUS8,3683
10
10
  shotgun/agents/__init__.py,sha256=8Jzv1YsDuLyNPFJyckSr_qI4ehTVeDyIMDW4omsfPGc,25
11
- shotgun/agents/agent_manager.py,sha256=xq8L0oAFgtFCpKVsyUoMtYJqUyz5XxjWLKNnxoe1zo4,26577
12
- shotgun/agents/common.py,sha256=BINebrcS9BcHu7yDH2yxTjChCmQoUCUrmUMlRnz4_JY,19265
11
+ shotgun/agents/agent_manager.py,sha256=6f86XooirrBRxyfTWRwsJk6M_kKaaoAP4Yfi6Lu7zGc,28995
12
+ shotgun/agents/common.py,sha256=g8QW782XZfZHjAJPC6k2uXqoX4UZufvbGaejzWgya8E,17768
13
13
  shotgun/agents/conversation_history.py,sha256=5J8_1yxdZiiWTq22aDio88DkBDZ4_Lh_p5Iy5_ENszc,3898
14
14
  shotgun/agents/conversation_manager.py,sha256=fxAvXbEl3Cl2ugJ4N9aWXaqZtkrnfj3QzwjWC4LFXwI,3514
15
- shotgun/agents/export.py,sha256=Zke952DbJ_lOBUmN-TPHw7qmjbfqsFu1uycBRQI_pkg,2969
15
+ shotgun/agents/export.py,sha256=7ZNw7781WJ4peLSeoUc7zxKeaZVxFpow2y4nU4dCfbo,2919
16
16
  shotgun/agents/llm.py,sha256=hs8j1wwTczGtehzahL1Z_5D4qus5QUx4-h9-m5ZPzm4,2209
17
17
  shotgun/agents/messages.py,sha256=wNn0qC5AqASM8LMaSGFOerZEJPn5FsIOmaJs1bdosuU,1036
18
- shotgun/agents/models.py,sha256=IvwwjbJYi5wi9S-budg8g1ezi1VaO57Q-XtegkbTrXg,8096
19
- shotgun/agents/plan.py,sha256=s-WfILBOW4l8kY59RUOVtX5MJSuSzFm1nGp6b17If78,3030
20
- shotgun/agents/research.py,sha256=lYG7Rytcitop8mXs3isMI3XvYzzI3JH9u0VZz6K9zfo,3274
21
- shotgun/agents/specify.py,sha256=7MoMxfIn34G27mw6wrp_F0i2O5rid476L3kHFONDCd0,3137
22
- shotgun/agents/tasks.py,sha256=nk8zIl24o01hfzOGyWSbeVWeke6OGseO4Ppciurh13U,2999
18
+ shotgun/agents/models.py,sha256=anNz8_U95B1__VPXgxFqfzk2BRIHrIO4clJlnfedVS8,9862
19
+ shotgun/agents/plan.py,sha256=lVhIoRUMCX2TsFbwbgKjS2HHhNreX35j_aZRqGxFAso,2980
20
+ shotgun/agents/research.py,sha256=EYqUda_wtrxmUNy6Mme3NFnO_uOXBCs94m2tZzheNOE,3224
21
+ shotgun/agents/specify.py,sha256=38z0n_7pAgWN3oJFuOxfiEHWtEqzMha-SyPhhZ9pWag,3087
22
+ shotgun/agents/tasks.py,sha256=AuriwtDn6uZz2G0eKfqBHYQrxYfJlbiAd-fcsw9lU3I,2949
23
23
  shotgun/agents/usage_manager.py,sha256=5d9JC4_cthXwhTSytMfMExMDAUYp8_nkPepTJZXk13w,5017
24
24
  shotgun/agents/config/__init__.py,sha256=Fl8K_81zBpm-OfOW27M_WWLSFdaHHek6lWz95iDREjQ,318
25
25
  shotgun/agents/config/constants.py,sha256=JNuLpeBUKikEsxGSjwX3RVWUQpbCKnDKstF2NczuDqk,932
26
- shotgun/agents/config/manager.py,sha256=AR3ENgt9zsJSyswOzc8XrnNIiMuq5hCbjU4n6S2ud4I,18699
26
+ shotgun/agents/config/manager.py,sha256=WO3TOwXCSOa7e3s_rmvH74jGw7xTqA_OaGhNaUsZ0a4,18922
27
27
  shotgun/agents/config/models.py,sha256=ohLXt9niCy4uFfFP1E6WSBZtxh7aZ16gTA2S3pHYkmc,5431
28
28
  shotgun/agents/config/provider.py,sha256=K2uW7DkdAhZfoDJcWV7NxOrSoEq1rQzArtZnxIgEe3E,12496
29
29
  shotgun/agents/history/__init__.py,sha256=XFQj2a6fxDqVg0Q3juvN9RjV_RJbgvFZtQOCOjVJyp4,147
@@ -35,15 +35,14 @@ shotgun/agents/history/history_processors.py,sha256=D3z-hzrXHxE7OAZaVX4_YAKN_nyx
35
35
  shotgun/agents/history/message_utils.py,sha256=aPusAl2RYKbjc7lBxPaNprRHmZEG6fe97q7DQUlhlzU,2918
36
36
  shotgun/agents/history/token_estimation.py,sha256=iRyKq-YDivEpJrULIbQgNpjhOuSC4nHVJYfsWEFV8sQ,4770
37
37
  shotgun/agents/history/token_counting/__init__.py,sha256=YZt5Lus--fkF6l1hdkIlp1e_oAIpACNwHOI0FRP4q8s,924
38
- shotgun/agents/history/token_counting/anthropic.py,sha256=fdRmm91od814mH1fSCv0WxmivEOy8xmcDIXJum1JaiE,3146
38
+ shotgun/agents/history/token_counting/anthropic.py,sha256=0Nf4mR7yjDbGyy8WguHse-sOENyU4X4CkthPjzbBaog,4031
39
39
  shotgun/agents/history/token_counting/base.py,sha256=TN4mzwSyWNQyTuOuCFaU-8AgLdAyquoX3af4qrmkxCs,1904
40
40
  shotgun/agents/history/token_counting/openai.py,sha256=XJ2z2HaUG6f3Cw9tCK_yaOsaMJGHpSFF1I30-d3soSI,2350
41
41
  shotgun/agents/history/token_counting/sentencepiece_counter.py,sha256=qj1bT7J5nCd5y6Mr42O9K1KTaele0rjdd09FeyyEA70,3987
42
42
  shotgun/agents/history/token_counting/tokenizer_cache.py,sha256=Y0V6KMtEwn42M5-zJGAc7YudM8X6m5-j2ekA6YGL5Xk,2868
43
43
  shotgun/agents/history/token_counting/utils.py,sha256=d124IDjtd0IYBYrr3gDJGWxSbdP10Vrc7ZistbUosMg,5002
44
- shotgun/agents/tools/__init__.py,sha256=QaN80IqWvB5qEcjHqri1-PYvYlO74vdhcwLugoEdblo,772
44
+ shotgun/agents/tools/__init__.py,sha256=kYppd4f4MoJcfTEPzkY2rqtxL1suXRGa9IRUm1G82GY,717
45
45
  shotgun/agents/tools/file_management.py,sha256=HYNe_QA4T3_bPzSWBYcFZcnWdj8eb4aQ3GB735-G8Nw,7138
46
- shotgun/agents/tools/user_interaction.py,sha256=b3ncEpvoD06Cz4hwsS-ppVbQajQj640iWnVfA5WBjAA,1236
47
46
  shotgun/agents/tools/codebase/__init__.py,sha256=ceAGkK006NeOYaIJBLQsw7Q46sAyCRK9PYDs8feMQVw,661
48
47
  shotgun/agents/tools/codebase/codebase_shell.py,sha256=9b7ZStAVFprdGqp1O23ZgwkToMytlUdp_R4MhvmENhc,8584
49
48
  shotgun/agents/tools/codebase/directory_lister.py,sha256=eX5GKDSmbKggKDvjPpYMa2WPSGPYQAtUEZ4eN01T0t8,4703
@@ -88,15 +87,15 @@ shotgun/llm_proxy/constants.py,sha256=_4piKdyvM7pAIRdAGrzYexwWoDlueUZiEMfwWrOa4T
88
87
  shotgun/prompts/__init__.py,sha256=RswUm0HMdfm2m2YKUwUsEdRIwoczdbI7zlucoEvHYRo,132
89
88
  shotgun/prompts/loader.py,sha256=_7CdUYrAo6ZwvTBUlXugKyLU0IDBg5CVzUIAHFPw418,4433
90
89
  shotgun/prompts/agents/__init__.py,sha256=YRIJMbzpArojNX1BP5gfxxois334z_GQga8T-xyWMbY,39
91
- shotgun/prompts/agents/export.j2,sha256=GKpOfGbZA9PVa4TNtMORUYiBIAcN6JCo8URmTCWKlWw,15936
92
- shotgun/prompts/agents/plan.j2,sha256=MyZDyOS21V-zrHNzbIhIdzcESGh_3KVbA4qh9rZR2_E,6086
93
- shotgun/prompts/agents/research.j2,sha256=JBtjXaMVDRuNTt7-Ai8gUb2InfolfqCkQoEkn9PsQZk,3929
90
+ shotgun/prompts/agents/export.j2,sha256=DGqVijH1PkpkY0rDauU52u_fMv15frEvOdXAPFZNMM4,17057
91
+ shotgun/prompts/agents/plan.j2,sha256=mbt505NdqmzmPxXzQYJS_gH5vkiVa2a3Dgz2K-15JZk,6093
92
+ shotgun/prompts/agents/research.j2,sha256=QFoSSiF_5v7c78RHaiucZEb9mOC_wF54BVKnJEH_DnI,3964
94
93
  shotgun/prompts/agents/specify.j2,sha256=AP7XrA3KE7GZsCvW4guASxZHBM2mnrMw3irdZ3RUOBs,2808
95
- shotgun/prompts/agents/tasks.j2,sha256=9gGCimCWVvpaQSxkAjt7WmIxFHXJY2FlmqhqomFxQTA,5949
94
+ shotgun/prompts/agents/tasks.j2,sha256=SMvTQPzRR6eHlW3fcj-7Bl-Lh9HWaiF3uAKv77nMdZw,5956
96
95
  shotgun/prompts/agents/partials/codebase_understanding.j2,sha256=7WH-PVd-TRBFQUdOdKkwwn9hAUaJznFZMAGHhO7IGGU,5633
97
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2,sha256=eFuc3z1pSJzQtPJfjMIDNHv5XX9lP6YVrmKcbbskJj8,1877
96
+ shotgun/prompts/agents/partials/common_agent_system_prompt.j2,sha256=wfjsQGcMTWWGBk9l0pKDnPehG8NrwTHm5FFEqba__LI,2161
98
97
  shotgun/prompts/agents/partials/content_formatting.j2,sha256=MG0JB7SSp8YV5akDWpbs2f9DcdREIYqLp38NnoWLeQ0,1854
99
- shotgun/prompts/agents/partials/interactive_mode.j2,sha256=9sYPbyc46HXg3k1FT_LugIQvOyNDnMQwsMIgOgN-_aY,1100
98
+ shotgun/prompts/agents/partials/interactive_mode.j2,sha256=nyNTURRszG_Pl7M3TS_luUshekDn9yVHfBDMkHSZ1kw,1448
100
99
  shotgun/prompts/agents/state/system_state.j2,sha256=RPweqBYmgWMiDuOjdEDl6NLgYU7HMaUGW1jBSnD5UzQ,1270
101
100
  shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2,sha256=U-hy-H9bPwV0sYIHTZ5TESxc5EOCtntI8GUZOmJipJw,601
102
101
  shotgun/prompts/codebase/__init__.py,sha256=NYuPMtmYM2ptuwf3YxVuotNlJOUq0hnjmwlzKcJkGK4,42
@@ -128,7 +127,7 @@ shotgun/tui/components/prompt_input.py,sha256=Ss-htqraHZAPaehGE4x86ij0veMjc4Ugad
128
127
  shotgun/tui/components/spinner.py,sha256=ovTDeaJ6FD6chZx_Aepia6R3UkPOVJ77EKHfRmn39MY,2427
129
128
  shotgun/tui/components/splash.py,sha256=vppy9vEIEvywuUKRXn2y11HwXSRkQZHLYoVjhDVdJeU,1267
130
129
  shotgun/tui/components/vertical_tail.py,sha256=kROwTaRjUwVB7H35dtmNcUVPQqNYvvfq7K2tXBKEb6c,638
131
- shotgun/tui/screens/chat.py,sha256=Yb5zWpWVmvtIFjO1jkhU6piJyGVc9XdTErNd6kUbjjw,30389
130
+ shotgun/tui/screens/chat.py,sha256=78GaZMKN2iE7bQQwiKBWFTsRoraWnuWl91qPjo5q1Nw,35446
132
131
  shotgun/tui/screens/chat.tcss,sha256=2Yq3E23jxsySYsgZf4G1AYrYVcpX0UDW6kNNI0tDmtM,437
133
132
  shotgun/tui/screens/directory_setup.py,sha256=lIZ1J4A6g5Q2ZBX8epW7BhR96Dmdcg22CyiM5S-I5WU,3237
134
133
  shotgun/tui/screens/feedback.py,sha256=VxpW0PVxMp22ZvSfQkTtgixNrpEOlfWtekjqlVfYEjA,5708
@@ -136,11 +135,11 @@ shotgun/tui/screens/model_picker.py,sha256=G-EvalpxgHKk0W3FgHMcxIr817VwZyEgh_Zad
136
135
  shotgun/tui/screens/provider_config.py,sha256=UCnAzjXPoP7Y73gsXxZF2PNA4LdSgpgoGYwiOd6fERA,10902
137
136
  shotgun/tui/screens/shotgun_auth.py,sha256=Y--7LZewV6gfDkucxymfAO7BCd7eI2C3H1ClDMztVio,10663
138
137
  shotgun/tui/screens/splash.py,sha256=E2MsJihi3c9NY1L28o_MstDxGwrCnnV7zdq00MrGAsw,706
139
- shotgun/tui/screens/welcome.py,sha256=r-RjtzjMhAaA0XKgnYKdZOuE07bcBi223fleKEf-Faw,5772
138
+ shotgun/tui/screens/welcome.py,sha256=XOKhd3hjhEUBjs9ZlUIZDdmrlIAvQ7qdO1_KKruGcqo,6134
140
139
  shotgun/tui/screens/chat_screen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
140
  shotgun/tui/screens/chat_screen/command_providers.py,sha256=7Xnxd4k30bpLOMZSX32bcugU4IgpqU4Y8f6eHWKXd4o,12694
142
141
  shotgun/tui/screens/chat_screen/hint_message.py,sha256=WOpbk8q7qt7eOHTyyHvh_IQIaublVDeJGaLpsxEk9FA,933
143
- shotgun/tui/screens/chat_screen/history.py,sha256=Go859iEjw0s5aELKpF42MjLXy7UFQ52XnJMTIkV3aLo,12406
142
+ shotgun/tui/screens/chat_screen/history.py,sha256=Bv7t1bcCf66X2qNEgwGMpPzNcxy4QZC4USshbctmJzA,12274
144
143
  shotgun/tui/utils/__init__.py,sha256=cFjDfoXTRBq29wgP7TGRWUu1eFfiIG-LLOzjIGfadgI,150
145
144
  shotgun/tui/utils/mode_progress.py,sha256=lseRRo7kMWLkBzI3cU5vqJmS2ZcCjyRYf9Zwtvc-v58,10931
146
145
  shotgun/utils/__init__.py,sha256=WinIEp9oL2iMrWaDkXz2QX4nYVPAm8C9aBSKTeEwLtE,198
@@ -149,8 +148,8 @@ shotgun/utils/env_utils.py,sha256=ulM3BRi9ZhS7uC-zorGeDQm4SHvsyFuuU9BtVPqdrHY,14
149
148
  shotgun/utils/file_system_utils.py,sha256=l-0p1bEHF34OU19MahnRFdClHufThfGAjQ431teAIp0,1004
150
149
  shotgun/utils/source_detection.py,sha256=Co6Q03R3fT771TF3RzB-70stfjNP2S4F_ArZKibwzm8,454
151
150
  shotgun/utils/update_checker.py,sha256=IgzPHRhS1ETH7PnJR_dIx6lxgr1qHpCkMTgzUxvGjhI,7586
152
- shotgun_sh-0.2.5.dist-info/METADATA,sha256=EFOMTry3j-nndQQf5YRJ5RCXxZkAoisYUSNCn1rCEZw,11221
153
- shotgun_sh-0.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
154
- shotgun_sh-0.2.5.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
155
- shotgun_sh-0.2.5.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
156
- shotgun_sh-0.2.5.dist-info/RECORD,,
151
+ shotgun_sh-0.2.6.dist-info/METADATA,sha256=PO0g-sqj_WTIr6dppso3IXwgk6wur5tJaP7TcSvEJAw,4263
152
+ shotgun_sh-0.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
153
+ shotgun_sh-0.2.6.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
154
+ shotgun_sh-0.2.6.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
155
+ shotgun_sh-0.2.6.dist-info/RECORD,,
@@ -1,37 +0,0 @@
1
- """User interaction tools for Pydantic AI agents."""
2
-
3
- from asyncio import get_running_loop
4
-
5
- from pydantic_ai import CallDeferred, RunContext
6
-
7
- from shotgun.agents.models import AgentDeps, UserQuestion
8
- from shotgun.logging_config import get_logger
9
-
10
- logger = get_logger(__name__)
11
-
12
-
13
- async def ask_user(ctx: RunContext[AgentDeps], question: str) -> str:
14
- """Ask the human a question and return the answer.
15
-
16
-
17
- Args:
18
- question: The question to ask the user with a clear CTA at the end. Needs to be is readable, clear, and easy to understand. Use Markdown formatting. Make key phrases and words stand out.
19
-
20
- Returns:
21
- The user's response as a string
22
- """
23
- tool_call_id = ctx.tool_call_id
24
- assert tool_call_id is not None # noqa: S101
25
-
26
- try:
27
- logger.debug("\n👉 %s\n", question)
28
- future = get_running_loop().create_future()
29
- await ctx.deps.queue.put(
30
- UserQuestion(question=question, tool_call_id=tool_call_id, result=future)
31
- )
32
- ctx.deps.tasks.append(future)
33
- raise CallDeferred(question)
34
-
35
- except (EOFError, KeyboardInterrupt):
36
- logger.warning("User input interrupted or unavailable")
37
- return "User input not available or interrupted"