shotgun-sh 0.2.5.dev1__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.
- shotgun/agents/agent_manager.py +103 -44
- shotgun/agents/common.py +13 -45
- shotgun/agents/config/manager.py +4 -0
- shotgun/agents/export.py +4 -5
- shotgun/agents/history/token_counting/anthropic.py +22 -2
- shotgun/agents/models.py +50 -2
- shotgun/agents/plan.py +4 -5
- shotgun/agents/research.py +4 -5
- shotgun/agents/specify.py +4 -5
- shotgun/agents/tasks.py +4 -5
- shotgun/agents/tools/__init__.py +0 -2
- shotgun/build_constants.py +2 -2
- shotgun/prompts/agents/export.j2 +18 -1
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +5 -1
- shotgun/prompts/agents/partials/interactive_mode.j2 +24 -7
- shotgun/prompts/agents/plan.j2 +1 -1
- shotgun/prompts/agents/research.j2 +1 -1
- shotgun/prompts/agents/tasks.j2 +1 -1
- shotgun/telemetry.py +8 -0
- shotgun/tui/screens/chat.py +185 -34
- shotgun/tui/screens/chat_screen/history.py +59 -76
- shotgun/tui/screens/welcome.py +10 -2
- shotgun_sh-0.2.6.dist-info/METADATA +125 -0
- {shotgun_sh-0.2.5.dev1.dist-info → shotgun_sh-0.2.6.dist-info}/RECORD +27 -28
- shotgun/agents/tools/user_interaction.py +0 -37
- shotgun_sh-0.2.5.dev1.dist-info/METADATA +0 -467
- {shotgun_sh-0.2.5.dev1.dist-info → shotgun_sh-0.2.6.dist-info}/WHEEL +0 -0
- {shotgun_sh-0.2.5.dev1.dist-info → shotgun_sh-0.2.6.dist-info}/entry_points.txt +0 -0
- {shotgun_sh-0.2.5.dev1.dist-info → shotgun_sh-0.2.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -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
|
-
|
|
107
|
-
|
|
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
|
-
|
|
193
|
-
|
|
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
|
-
|
|
189
|
+
if parts_str: # Only add if there's actual content
|
|
190
|
+
acc += parts_str + "\n\n"
|
|
226
191
|
elif isinstance(part, BuiltinToolCallPart):
|
|
227
|
-
|
|
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
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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 == "
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
350
|
-
|
|
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}()"
|
shotgun/tui/screens/welcome.py
CHANGED
|
@@ -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.
|
|
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+
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
shotgun/__init__.py,sha256=P40K0fnIsb7SKcQrFnXZ4aREjpWchVDhvM1HxI4cyIQ,104
|
|
2
2
|
shotgun/api_endpoints.py,sha256=TvxuJyMrZLy6KZTrR6lrdkG8OBtb3TJ48qaw3pWitO0,526
|
|
3
|
-
shotgun/build_constants.py,sha256=
|
|
3
|
+
shotgun/build_constants.py,sha256=hDFr6eO0lwN0iCqHQ1A5s0D68txR8sYrTJLGa7tSi0o,654
|
|
4
4
|
shotgun/logging_config.py,sha256=UKenihvgH8OA3W0b8ZFcItYaFJVe9MlsMYlcevyW1HY,7440
|
|
5
5
|
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=
|
|
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=
|
|
12
|
-
shotgun/agents/common.py,sha256=
|
|
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=
|
|
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=
|
|
19
|
-
shotgun/agents/plan.py,sha256=
|
|
20
|
-
shotgun/agents/research.py,sha256=
|
|
21
|
-
shotgun/agents/specify.py,sha256=
|
|
22
|
-
shotgun/agents/tasks.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
92
|
-
shotgun/prompts/agents/plan.j2,sha256=
|
|
93
|
-
shotgun/prompts/agents/research.j2,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
153
|
-
shotgun_sh-0.2.
|
|
154
|
-
shotgun_sh-0.2.
|
|
155
|
-
shotgun_sh-0.2.
|
|
156
|
-
shotgun_sh-0.2.
|
|
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"
|