shotgun-sh 0.1.0.dev12__py3-none-any.whl → 0.1.0.dev13__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/common.py +94 -79
- shotgun/agents/config/constants.py +18 -0
- shotgun/agents/config/manager.py +68 -16
- shotgun/agents/config/provider.py +11 -6
- shotgun/agents/models.py +6 -0
- shotgun/agents/plan.py +15 -37
- shotgun/agents/research.py +10 -45
- shotgun/agents/specify.py +97 -0
- shotgun/agents/tasks.py +7 -36
- shotgun/agents/tools/artifact_management.py +450 -0
- shotgun/agents/tools/file_management.py +2 -2
- shotgun/artifacts/__init__.py +17 -0
- shotgun/artifacts/exceptions.py +89 -0
- shotgun/artifacts/manager.py +529 -0
- shotgun/artifacts/models.py +332 -0
- shotgun/artifacts/service.py +463 -0
- shotgun/artifacts/templates/__init__.py +10 -0
- shotgun/artifacts/templates/loader.py +252 -0
- shotgun/artifacts/templates/models.py +136 -0
- shotgun/artifacts/templates/plan/delivery_and_release_plan.yaml +66 -0
- shotgun/artifacts/templates/research/market_research.yaml +585 -0
- shotgun/artifacts/templates/research/sdk_comparison.yaml +257 -0
- shotgun/artifacts/templates/specify/prd.yaml +331 -0
- shotgun/artifacts/templates/specify/product_spec.yaml +301 -0
- shotgun/artifacts/utils.py +76 -0
- shotgun/cli/plan.py +1 -4
- shotgun/cli/specify.py +69 -0
- shotgun/cli/tasks.py +0 -4
- shotgun/logging_config.py +23 -7
- shotgun/main.py +7 -6
- shotgun/prompts/agents/partials/artifact_system.j2 +32 -0
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +28 -2
- shotgun/prompts/agents/partials/content_formatting.j2 +65 -0
- shotgun/prompts/agents/partials/interactive_mode.j2 +10 -2
- shotgun/prompts/agents/plan.j2 +31 -32
- shotgun/prompts/agents/research.j2 +37 -29
- shotgun/prompts/agents/specify.j2 +31 -0
- shotgun/prompts/agents/tasks.j2 +27 -12
- shotgun/sdk/artifact_models.py +186 -0
- shotgun/sdk/artifacts.py +448 -0
- shotgun/tui/app.py +26 -7
- shotgun/tui/screens/chat.py +28 -3
- shotgun/tui/screens/directory_setup.py +113 -0
- {shotgun_sh-0.1.0.dev12.dist-info → shotgun_sh-0.1.0.dev13.dist-info}/METADATA +2 -2
- {shotgun_sh-0.1.0.dev12.dist-info → shotgun_sh-0.1.0.dev13.dist-info}/RECORD +48 -25
- shotgun/prompts/user/research.j2 +0 -5
- {shotgun_sh-0.1.0.dev12.dist-info → shotgun_sh-0.1.0.dev13.dist-info}/WHEEL +0 -0
- {shotgun_sh-0.1.0.dev12.dist-info → shotgun_sh-0.1.0.dev13.dist-info}/entry_points.txt +0 -0
- {shotgun_sh-0.1.0.dev12.dist-info → shotgun_sh-0.1.0.dev13.dist-info}/licenses/LICENSE +0 -0
shotgun/agents/research.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Research agent factory and functions using Pydantic AI with file-based memory."""
|
|
2
2
|
|
|
3
|
+
from functools import partial
|
|
4
|
+
|
|
3
5
|
from pydantic_ai import (
|
|
4
6
|
Agent,
|
|
5
7
|
DeferredToolRequests,
|
|
6
|
-
RunContext,
|
|
7
8
|
)
|
|
8
9
|
from pydantic_ai.agent import AgentRunResult
|
|
9
10
|
from pydantic_ai.messages import (
|
|
@@ -12,14 +13,12 @@ from pydantic_ai.messages import (
|
|
|
12
13
|
|
|
13
14
|
from shotgun.agents.config import ProviderType
|
|
14
15
|
from shotgun.logging_config import get_logger
|
|
15
|
-
from shotgun.prompts import PromptLoader
|
|
16
16
|
|
|
17
17
|
from .common import (
|
|
18
18
|
add_system_status_message,
|
|
19
|
+
build_agent_system_prompt,
|
|
19
20
|
create_base_agent,
|
|
20
21
|
create_usage_limits,
|
|
21
|
-
ensure_file_exists,
|
|
22
|
-
get_file_history,
|
|
23
22
|
run_agent,
|
|
24
23
|
)
|
|
25
24
|
from .models import AgentDeps, AgentRuntimeOptions
|
|
@@ -27,30 +26,11 @@ from .tools import get_available_web_search_tools
|
|
|
27
26
|
|
|
28
27
|
logger = get_logger(__name__)
|
|
29
28
|
|
|
30
|
-
# Global prompt loader instance
|
|
31
|
-
prompt_loader = PromptLoader()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _build_research_agent_system_prompt(ctx: RunContext[AgentDeps]) -> str:
|
|
35
|
-
"""Build the system prompt for the research agent.
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
ctx: RunContext containing AgentDeps with interactive_mode and other settings
|
|
39
|
-
|
|
40
|
-
Returns:
|
|
41
|
-
The complete system prompt string for the research agent
|
|
42
|
-
"""
|
|
43
|
-
return prompt_loader.render(
|
|
44
|
-
"agents/research.j2",
|
|
45
|
-
interactive_mode=ctx.deps.interactive_mode,
|
|
46
|
-
context="research output",
|
|
47
|
-
)
|
|
48
|
-
|
|
49
29
|
|
|
50
30
|
def create_research_agent(
|
|
51
31
|
agent_runtime_options: AgentRuntimeOptions, provider: ProviderType | None = None
|
|
52
32
|
) -> tuple[Agent[AgentDeps, str | DeferredToolRequests], AgentDeps]:
|
|
53
|
-
"""Create a research agent with web search capabilities.
|
|
33
|
+
"""Create a research agent with web search and artifact management capabilities.
|
|
54
34
|
|
|
55
35
|
Args:
|
|
56
36
|
agent_runtime_options: Agent runtime options for the agent
|
|
@@ -71,8 +51,11 @@ def create_research_agent(
|
|
|
71
51
|
else:
|
|
72
52
|
logger.warning("Research agent configured without web search tools")
|
|
73
53
|
|
|
54
|
+
# Use partial to create system prompt function for research agent
|
|
55
|
+
system_prompt_fn = partial(build_agent_system_prompt, "research")
|
|
56
|
+
|
|
74
57
|
agent, deps = create_base_agent(
|
|
75
|
-
|
|
58
|
+
system_prompt_fn,
|
|
76
59
|
agent_runtime_options,
|
|
77
60
|
load_codebase_understanding_tools=True,
|
|
78
61
|
additional_tools=web_search_tools,
|
|
@@ -87,7 +70,7 @@ async def run_research_agent(
|
|
|
87
70
|
deps: AgentDeps,
|
|
88
71
|
message_history: list[ModelMessage] | None = None,
|
|
89
72
|
) -> AgentRunResult[str | DeferredToolRequests]:
|
|
90
|
-
"""Perform research on the given query and update
|
|
73
|
+
"""Perform research on the given query and update research artifacts.
|
|
91
74
|
|
|
92
75
|
Args:
|
|
93
76
|
agent: The configured research agent
|
|
@@ -99,24 +82,15 @@ async def run_research_agent(
|
|
|
99
82
|
"""
|
|
100
83
|
logger.debug("🔬 Starting research for query: %s", query)
|
|
101
84
|
|
|
102
|
-
# Ensure research.md exists
|
|
103
|
-
ensure_file_exists("research.md", "# Research")
|
|
104
|
-
|
|
105
85
|
message_history = await add_system_status_message(deps, message_history)
|
|
106
86
|
|
|
107
|
-
user_prompt = prompt_loader.render(
|
|
108
|
-
"user/research.j2",
|
|
109
|
-
user_query=query,
|
|
110
|
-
context="research output",
|
|
111
|
-
)
|
|
112
|
-
|
|
113
87
|
try:
|
|
114
88
|
# Create usage limits for responsible API usage
|
|
115
89
|
usage_limits = create_usage_limits()
|
|
116
90
|
|
|
117
91
|
result = await run_agent(
|
|
118
92
|
agent=agent,
|
|
119
|
-
prompt=
|
|
93
|
+
prompt=query,
|
|
120
94
|
deps=deps,
|
|
121
95
|
message_history=message_history,
|
|
122
96
|
usage_limits=usage_limits,
|
|
@@ -131,12 +105,3 @@ async def run_research_agent(
|
|
|
131
105
|
logger.error("Full traceback:\n%s", traceback.format_exc())
|
|
132
106
|
logger.error("❌ Research failed: %s", str(e))
|
|
133
107
|
raise
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def get_research_history() -> str:
|
|
137
|
-
"""Get the full research history from the file.
|
|
138
|
-
|
|
139
|
-
Returns:
|
|
140
|
-
Research history content or fallback message
|
|
141
|
-
"""
|
|
142
|
-
return get_file_history("research.md")
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Specify agent factory and functions using Pydantic AI with file-based memory."""
|
|
2
|
+
|
|
3
|
+
from functools import partial
|
|
4
|
+
|
|
5
|
+
from pydantic_ai import (
|
|
6
|
+
Agent,
|
|
7
|
+
DeferredToolRequests,
|
|
8
|
+
)
|
|
9
|
+
from pydantic_ai.agent import AgentRunResult
|
|
10
|
+
from pydantic_ai.messages import ModelMessage
|
|
11
|
+
|
|
12
|
+
from shotgun.agents.config import ProviderType
|
|
13
|
+
from shotgun.logging_config import get_logger
|
|
14
|
+
|
|
15
|
+
from .common import (
|
|
16
|
+
add_system_status_message,
|
|
17
|
+
build_agent_system_prompt,
|
|
18
|
+
create_base_agent,
|
|
19
|
+
create_usage_limits,
|
|
20
|
+
run_agent,
|
|
21
|
+
)
|
|
22
|
+
from .models import AgentDeps, AgentRuntimeOptions
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_specify_agent(
|
|
28
|
+
agent_runtime_options: AgentRuntimeOptions, provider: ProviderType | None = None
|
|
29
|
+
) -> tuple[Agent[AgentDeps, str | DeferredToolRequests], AgentDeps]:
|
|
30
|
+
"""Create a specify agent with artifact management capabilities.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
agent_runtime_options: Agent runtime options for the agent
|
|
34
|
+
provider: Optional provider override. If None, uses configured default
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Tuple of (Configured Pydantic AI agent for specification tasks, Agent dependencies)
|
|
38
|
+
"""
|
|
39
|
+
logger.debug("Initializing specify agent")
|
|
40
|
+
# Use partial to create system prompt function for specify agent
|
|
41
|
+
system_prompt_fn = partial(build_agent_system_prompt, "specify")
|
|
42
|
+
|
|
43
|
+
agent, deps = create_base_agent(
|
|
44
|
+
system_prompt_fn,
|
|
45
|
+
agent_runtime_options,
|
|
46
|
+
load_codebase_understanding_tools=True,
|
|
47
|
+
additional_tools=None,
|
|
48
|
+
provider=provider,
|
|
49
|
+
)
|
|
50
|
+
return agent, deps
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def run_specify_agent(
|
|
54
|
+
agent: Agent[AgentDeps, str | DeferredToolRequests],
|
|
55
|
+
requirement: str,
|
|
56
|
+
deps: AgentDeps,
|
|
57
|
+
message_history: list[ModelMessage] | None = None,
|
|
58
|
+
) -> AgentRunResult[str | DeferredToolRequests]:
|
|
59
|
+
"""Create or update specifications based on the given requirement.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
agent: The configured specify agent
|
|
63
|
+
requirement: The specification requirement or instruction
|
|
64
|
+
deps: Agent dependencies
|
|
65
|
+
message_history: Optional message history for conversation continuity
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
AgentRunResult containing the specification process output
|
|
69
|
+
"""
|
|
70
|
+
logger.debug("📋 Starting specification for requirement: %s", requirement)
|
|
71
|
+
|
|
72
|
+
# Simple prompt - the agent system prompt has all the artifact instructions
|
|
73
|
+
full_prompt = f"Create a comprehensive specification for: {requirement}"
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
# Create usage limits for responsible API usage
|
|
77
|
+
usage_limits = create_usage_limits()
|
|
78
|
+
|
|
79
|
+
message_history = await add_system_status_message(deps, message_history)
|
|
80
|
+
|
|
81
|
+
result = await run_agent(
|
|
82
|
+
agent=agent,
|
|
83
|
+
prompt=full_prompt,
|
|
84
|
+
deps=deps,
|
|
85
|
+
message_history=message_history,
|
|
86
|
+
usage_limits=usage_limits,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
logger.debug("✅ Specification completed successfully")
|
|
90
|
+
return result
|
|
91
|
+
|
|
92
|
+
except Exception as e:
|
|
93
|
+
import traceback
|
|
94
|
+
|
|
95
|
+
logger.error("Full traceback:\n%s", traceback.format_exc())
|
|
96
|
+
logger.error("❌ Specification failed: %s", str(e))
|
|
97
|
+
raise
|
shotgun/agents/tasks.py
CHANGED
|
@@ -1,48 +1,28 @@
|
|
|
1
1
|
"""Tasks agent factory and functions using Pydantic AI with file-based memory."""
|
|
2
2
|
|
|
3
|
+
from functools import partial
|
|
4
|
+
|
|
3
5
|
from pydantic_ai import (
|
|
4
6
|
Agent,
|
|
5
7
|
DeferredToolRequests,
|
|
6
|
-
RunContext,
|
|
7
8
|
)
|
|
8
9
|
from pydantic_ai.agent import AgentRunResult
|
|
9
10
|
from pydantic_ai.messages import ModelMessage
|
|
10
11
|
|
|
11
12
|
from shotgun.agents.config import ProviderType
|
|
12
13
|
from shotgun.logging_config import get_logger
|
|
13
|
-
from shotgun.prompts import PromptLoader
|
|
14
14
|
|
|
15
15
|
from .common import (
|
|
16
16
|
add_system_status_message,
|
|
17
|
+
build_agent_system_prompt,
|
|
17
18
|
create_base_agent,
|
|
18
19
|
create_usage_limits,
|
|
19
|
-
ensure_file_exists,
|
|
20
|
-
get_file_history,
|
|
21
20
|
run_agent,
|
|
22
21
|
)
|
|
23
22
|
from .models import AgentDeps, AgentRuntimeOptions
|
|
24
23
|
|
|
25
24
|
logger = get_logger(__name__)
|
|
26
25
|
|
|
27
|
-
# Global prompt loader instance
|
|
28
|
-
prompt_loader = PromptLoader()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def _build_tasks_agent_system_prompt(ctx: RunContext[AgentDeps]) -> str:
|
|
32
|
-
"""Build the system prompt for the tasks agent.
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
ctx: RunContext containing AgentDeps with interactive_mode and other settings
|
|
36
|
-
|
|
37
|
-
Returns:
|
|
38
|
-
The complete system prompt string for the tasks agent
|
|
39
|
-
"""
|
|
40
|
-
return prompt_loader.render(
|
|
41
|
-
"agents/tasks.j2",
|
|
42
|
-
interactive_mode=ctx.deps.interactive_mode,
|
|
43
|
-
context="task lists",
|
|
44
|
-
)
|
|
45
|
-
|
|
46
26
|
|
|
47
27
|
def create_tasks_agent(
|
|
48
28
|
agent_runtime_options: AgentRuntimeOptions, provider: ProviderType | None = None
|
|
@@ -57,8 +37,11 @@ def create_tasks_agent(
|
|
|
57
37
|
Tuple of (Configured Pydantic AI agent for task management, Agent dependencies)
|
|
58
38
|
"""
|
|
59
39
|
logger.debug("Initializing tasks agent")
|
|
40
|
+
# Use partial to create system prompt function for tasks agent
|
|
41
|
+
system_prompt_fn = partial(build_agent_system_prompt, "tasks")
|
|
42
|
+
|
|
60
43
|
agent, deps = create_base_agent(
|
|
61
|
-
|
|
44
|
+
system_prompt_fn, agent_runtime_options, provider=provider
|
|
62
45
|
)
|
|
63
46
|
return agent, deps
|
|
64
47
|
|
|
@@ -82,9 +65,6 @@ async def run_tasks_agent(
|
|
|
82
65
|
"""
|
|
83
66
|
logger.debug("📋 Starting task creation for instruction: %s", instruction)
|
|
84
67
|
|
|
85
|
-
# Ensure tasks.md exists
|
|
86
|
-
ensure_file_exists("tasks.md", "# Tasks")
|
|
87
|
-
|
|
88
68
|
message_history = await add_system_status_message(deps, message_history)
|
|
89
69
|
|
|
90
70
|
# Let the agent use its tools to read existing tasks, plan, and research
|
|
@@ -111,12 +91,3 @@ async def run_tasks_agent(
|
|
|
111
91
|
logger.error("Full traceback:\n%s", traceback.format_exc())
|
|
112
92
|
logger.error("❌ Task creation failed: %s", str(e))
|
|
113
93
|
raise
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def get_tasks_history() -> str:
|
|
117
|
-
"""Get the full tasks history from the file.
|
|
118
|
-
|
|
119
|
-
Returns:
|
|
120
|
-
Tasks history content or fallback message
|
|
121
|
-
"""
|
|
122
|
-
return get_file_history("tasks.md")
|