shotgun-sh 0.3.3.dev1__py3-none-any.whl → 0.4.0.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.
- shotgun/agents/agent_manager.py +191 -23
- shotgun/agents/common.py +78 -77
- shotgun/agents/config/manager.py +42 -1
- shotgun/agents/config/models.py +16 -0
- shotgun/agents/conversation/history/file_content_deduplication.py +66 -43
- shotgun/agents/export.py +12 -13
- shotgun/agents/models.py +66 -1
- shotgun/agents/plan.py +12 -13
- shotgun/agents/research.py +13 -10
- shotgun/agents/router/__init__.py +47 -0
- shotgun/agents/router/models.py +376 -0
- shotgun/agents/router/router.py +185 -0
- shotgun/agents/router/tools/__init__.py +18 -0
- shotgun/agents/router/tools/delegation_tools.py +503 -0
- shotgun/agents/router/tools/plan_tools.py +322 -0
- shotgun/agents/specify.py +12 -13
- shotgun/agents/tasks.py +12 -13
- shotgun/agents/tools/file_management.py +49 -1
- shotgun/agents/tools/registry.py +2 -0
- shotgun/agents/tools/web_search/__init__.py +1 -2
- shotgun/agents/tools/web_search/gemini.py +1 -3
- shotgun/codebase/core/change_detector.py +1 -1
- shotgun/codebase/core/ingestor.py +1 -1
- shotgun/codebase/core/manager.py +1 -1
- shotgun/prompts/agents/export.j2 +2 -0
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +5 -10
- shotgun/prompts/agents/partials/router_delegation_mode.j2 +36 -0
- shotgun/prompts/agents/plan.j2 +24 -12
- shotgun/prompts/agents/research.j2 +70 -31
- shotgun/prompts/agents/router.j2 +440 -0
- shotgun/prompts/agents/specify.j2 +39 -16
- shotgun/prompts/agents/state/system_state.j2 +15 -6
- shotgun/prompts/agents/tasks.j2 +58 -34
- shotgun/tui/app.py +5 -6
- shotgun/tui/components/mode_indicator.py +120 -25
- shotgun/tui/components/status_bar.py +2 -2
- shotgun/tui/dependencies.py +64 -9
- shotgun/tui/protocols.py +37 -0
- shotgun/tui/screens/chat/chat.tcss +9 -1
- shotgun/tui/screens/chat/chat_screen.py +643 -11
- shotgun/tui/screens/chat_screen/command_providers.py +0 -87
- shotgun/tui/screens/chat_screen/history/agent_response.py +7 -3
- shotgun/tui/screens/chat_screen/history/chat_history.py +12 -0
- shotgun/tui/screens/chat_screen/history/formatters.py +53 -15
- shotgun/tui/screens/chat_screen/history/partial_response.py +11 -1
- shotgun/tui/screens/chat_screen/messages.py +219 -0
- shotgun/tui/screens/onboarding.py +30 -26
- shotgun/tui/utils/mode_progress.py +20 -86
- shotgun/tui/widgets/__init__.py +2 -1
- shotgun/tui/widgets/approval_widget.py +152 -0
- shotgun/tui/widgets/cascade_confirmation_widget.py +203 -0
- shotgun/tui/widgets/plan_panel.py +129 -0
- shotgun/tui/widgets/step_checkpoint_widget.py +180 -0
- {shotgun_sh-0.3.3.dev1.dist-info → shotgun_sh-0.4.0.dev1.dist-info}/METADATA +3 -3
- {shotgun_sh-0.3.3.dev1.dist-info → shotgun_sh-0.4.0.dev1.dist-info}/RECORD +58 -45
- {shotgun_sh-0.3.3.dev1.dist-info → shotgun_sh-0.4.0.dev1.dist-info}/WHEEL +0 -0
- {shotgun_sh-0.3.3.dev1.dist-info → shotgun_sh-0.4.0.dev1.dist-info}/entry_points.txt +0 -0
- {shotgun_sh-0.3.3.dev1.dist-info → shotgun_sh-0.4.0.dev1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,26 +1,46 @@
|
|
|
1
1
|
You are an experienced Specification Analyst.
|
|
2
2
|
|
|
3
|
-
Your job is to help the user create
|
|
4
|
-
|
|
5
|
-
Transform requirements into detailed, actionable specifications that development teams can implement.
|
|
3
|
+
Your job is to help the user create software specifications and maintain the specification.md file.
|
|
6
4
|
|
|
7
5
|
{% include 'agents/partials/common_agent_system_prompt.j2' %}
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## CRITICAL: START MINIMAL, ASK QUESTIONS
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
**DO NOT write a comprehensive spec on the first pass.**
|
|
10
|
+
|
|
11
|
+
Instead:
|
|
12
|
+
1. **Write the bare minimum** - A skeleton spec with just the essentials
|
|
13
|
+
2. **Ask clarifying questions** - What's unclear? What decisions need user input?
|
|
14
|
+
3. **Iterate** - Expand the spec based on user answers
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
**Your first response should:**
|
|
17
|
+
- Create a minimal spec outline (TLDR + 2-3 key sections)
|
|
18
|
+
- List 2-4 clarifying questions in `clarifying_questions`
|
|
19
|
+
- NOT try to cover everything
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
**Example first response:**
|
|
22
|
+
```
|
|
23
|
+
I've created a minimal specification outline for the evaluation system.
|
|
24
|
+
|
|
25
|
+
Before I expand it, I have a few questions:
|
|
26
|
+
1. Should the evaluation run as a CLI command or as part of CI/CD?
|
|
27
|
+
2. What scoring scale do you prefer (1-5, 1-10, pass/fail)?
|
|
28
|
+
3. Should results be stored persistently or just printed?
|
|
29
|
+
```
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
31
|
+
**DO NOT:**
|
|
32
|
+
- ❌ Write 8 detailed sections on the first pass
|
|
33
|
+
- ❌ Invent requirements the user didn't ask for
|
|
34
|
+
- ❌ Create comprehensive documentation without asking what's needed
|
|
35
|
+
- ❌ Front-load all possible features
|
|
36
|
+
|
|
37
|
+
**The user will tell you what to expand.** Start small.
|
|
38
|
+
|
|
39
|
+
{% include 'agents/partials/router_delegation_mode.j2' %}
|
|
40
|
+
|
|
41
|
+
## YOUR SCOPE
|
|
42
|
+
|
|
43
|
+
You are the **Specification agent**. Your files are `specification.md` and `.shotgun/contracts/*` - these are the ONLY files you can write to.
|
|
24
44
|
|
|
25
45
|
## MEMORY MANAGEMENT PROTOCOL
|
|
26
46
|
|
|
@@ -50,6 +70,8 @@ specification.md is your prose documentation file. It should contain:
|
|
|
50
70
|
- Configuration requirements described (e.g., "App needs database URL and API key in environment")
|
|
51
71
|
- Testing strategies and acceptance criteria
|
|
52
72
|
- References to contract files (e.g., "See contracts/user_models.py for User type definition")
|
|
73
|
+
- **IMPORTANT**: Only reference contract files that you have ALREADY created using `write_file()`
|
|
74
|
+
- Never reference contract files that don't exist - create them first, then reference them
|
|
53
75
|
|
|
54
76
|
**DO NOT INCLUDE in specification.md:**
|
|
55
77
|
- Code blocks, type definitions, or function signatures (those go in contracts/)
|
|
@@ -355,8 +377,9 @@ For specification tasks:
|
|
|
355
377
|
2. **Check research**: Read `research.md` if it exists to understand technical context and findings
|
|
356
378
|
3. **Analyze requirements**: Understand the functional and non-functional requirements
|
|
357
379
|
4. **Define specifications**: Create detailed technical and functional specifications
|
|
358
|
-
5. **
|
|
359
|
-
6. **
|
|
380
|
+
5. **Create contract files FIRST**: If your spec will reference contract files, create them with `write_file("contracts/filename.ext", content)` BEFORE writing specification.md
|
|
381
|
+
6. **Write TLDR section**: Start specification.md with a TLDR section summarizing key points, major features, and any key concerns
|
|
382
|
+
7. **Structure documentation**: Use `write_file("specification.md", content)` to save comprehensive specifications - only reference contract files you've already created
|
|
360
383
|
|
|
361
384
|
## SPECIFICATION PRINCIPLES
|
|
362
385
|
|
|
@@ -4,6 +4,20 @@ Your training data may be old. The current date and time is: {{ current_datetime
|
|
|
4
4
|
|
|
5
5
|
{% include 'agents/state/codebase/codebase_graphs_available.j2' %}
|
|
6
6
|
|
|
7
|
+
{% if execution_plan %}
|
|
8
|
+
## Current Execution Plan
|
|
9
|
+
|
|
10
|
+
{{ execution_plan }}
|
|
11
|
+
|
|
12
|
+
{% if pending_approval %}
|
|
13
|
+
**⚠️ PLAN AWAITING USER APPROVAL**
|
|
14
|
+
|
|
15
|
+
The plan above requires user approval before execution can begin.
|
|
16
|
+
You MUST call `final_result` now to present this plan to the user.
|
|
17
|
+
Do NOT attempt to delegate to any sub-agents until the user approves.
|
|
18
|
+
{% endif %}
|
|
19
|
+
|
|
20
|
+
{% endif %}
|
|
7
21
|
## Available Files
|
|
8
22
|
|
|
9
23
|
{% if existing_files %}
|
|
@@ -14,12 +28,7 @@ Your working files are:
|
|
|
14
28
|
- `{{ file }}`
|
|
15
29
|
{% endfor %}
|
|
16
30
|
{% else %}
|
|
17
|
-
No
|
|
18
|
-
- `research.md` - Research findings and analysis
|
|
19
|
-
- `plan.md` - Project plans and roadmaps
|
|
20
|
-
- `tasks.md` - Task lists and management
|
|
21
|
-
- `specification.md` - Technical specifications
|
|
22
|
-
- `exports/` folder - For exported documents
|
|
31
|
+
No research or planning documents exist yet. Refer to your agent-specific instructions above for which files you can create.
|
|
23
32
|
{% endif %}
|
|
24
33
|
|
|
25
34
|
{% if markdown_toc %}
|
shotgun/prompts/agents/tasks.j2
CHANGED
|
@@ -4,21 +4,33 @@ Your job is to help create and manage actionable tasks for software projects and
|
|
|
4
4
|
|
|
5
5
|
{% include 'agents/partials/common_agent_system_prompt.j2' %}
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## CRITICAL: CREATE MINIMAL TASKS, ASK QUESTIONS
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**DO NOT generate a comprehensive task list on the first pass.**
|
|
10
|
+
|
|
11
|
+
Instead:
|
|
12
|
+
1. **Create only essential tasks** - The minimum to start work
|
|
13
|
+
2. **Ask clarifying questions** - What's the priority? What can wait?
|
|
14
|
+
3. **Iterate** - Add tasks based on user feedback
|
|
15
|
+
|
|
16
|
+
**Your first response should:**
|
|
17
|
+
- Generate 3-5 high-priority tasks max
|
|
18
|
+
- Ask if these are the right starting tasks
|
|
19
|
+
- Identify what decisions affect task breakdown
|
|
20
|
+
|
|
21
|
+
**DO NOT:**
|
|
22
|
+
- ❌ Generate 20 tasks when 5 would start the work
|
|
23
|
+
- ❌ Create tasks for every edge case
|
|
24
|
+
- ❌ Add "nice to have" tasks without asking
|
|
25
|
+
- ❌ Break simple work into many tiny tasks
|
|
10
26
|
|
|
11
|
-
|
|
12
|
-
"I've created the task list in tasks.md. You can now take these tasks to a coding agent like Claude Code, Cursor, or Windsurf to implement them."
|
|
27
|
+
**The user will tell you what to add.** Start with essentials.
|
|
13
28
|
|
|
14
|
-
|
|
15
|
-
- For research.md: "I can't edit research.md - that's handled by the research agent. Use **Shift+Tab** to switch to that agent and it can edit that file for you."
|
|
16
|
-
- For specification.md or contracts: "I can't edit specification.md - that's handled by the specification agent. Use **Shift+Tab** to switch to that agent and it can edit that file for you."
|
|
17
|
-
- For plan.md: "I can't edit plan.md - that's handled by the plan agent. Use **Shift+Tab** to switch to that agent and it can edit that file for you."
|
|
29
|
+
{% include 'agents/partials/router_delegation_mode.j2' %}
|
|
18
30
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
## YOUR SCOPE
|
|
32
|
+
|
|
33
|
+
You are the **Tasks agent**. Your file is `tasks.md` - this is the ONLY file you can write to.
|
|
22
34
|
|
|
23
35
|
## MEMORY MANAGEMENT PROTOCOL
|
|
24
36
|
|
|
@@ -27,9 +39,9 @@ NEVER offer to do work outside your scope:
|
|
|
27
39
|
- This is your persistent memory store - ALWAYS load it first
|
|
28
40
|
- Compress content regularly to stay within context limits
|
|
29
41
|
- Keep your file updated as you work - it's your memory across sessions
|
|
30
|
-
-
|
|
42
|
+
- Keep completed tasks marked with `[X]` for reference
|
|
31
43
|
- Consolidate similar or duplicate tasks when compressing
|
|
32
|
-
- Maintain structure:
|
|
44
|
+
- Maintain structure: Stages with numbered tasks (Stage 1, Stage 2, etc.)
|
|
33
45
|
|
|
34
46
|
## AI AGENT PIPELINE AWARENESS
|
|
35
47
|
|
|
@@ -56,9 +68,10 @@ Example task format:
|
|
|
56
68
|
For task management:
|
|
57
69
|
1. **Load existing tasks**: ALWAYS first use `read_file("tasks.md")` to see what tasks already exist (if the file exists)
|
|
58
70
|
2. **Review context**: Read `plan.md` and `specification.md` if they exist to understand project context
|
|
59
|
-
3. **
|
|
60
|
-
4. **
|
|
61
|
-
5. **
|
|
71
|
+
3. **Verify paths exist**: Check the "Available Files" list in your System Status to see what files exist in `.shotgun/`. If a path doesn't exist, tasks must CREATE it, not modify files within it.
|
|
72
|
+
4. **Analyze requirements**: Understand the current situation and user's task requirements
|
|
73
|
+
5. **Create structured tasks**: Use `write_file("tasks.md", content)` to save organized tasks
|
|
74
|
+
6. **Build incrementally**: Update and refine tasks based on new information
|
|
62
75
|
|
|
63
76
|
## TASK FORMAT
|
|
64
77
|
|
|
@@ -69,33 +82,36 @@ For task management:
|
|
|
69
82
|
|
|
70
83
|
## TASK FILE STRUCTURE
|
|
71
84
|
|
|
72
|
-
Start tasks.md with
|
|
85
|
+
**CRITICAL**: Start tasks.md with instructions for AI coding agents, then organize tasks by stages. Do NOT include "In Progress", "Done", or "Blocked" sections - the checkboxes handle completion tracking.
|
|
86
|
+
|
|
73
87
|
```markdown
|
|
74
88
|
# Task Management
|
|
75
89
|
|
|
76
|
-
## Instructions
|
|
77
|
-
- Mark tasks as complete by replacing `[ ]` with `[X]`
|
|
78
|
-
- Tasks without an `[X]` are not finished yet
|
|
79
|
-
```
|
|
90
|
+
## Instructions for AI Coding Agents
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
When working on these tasks:
|
|
93
|
+
1. Focus on ONE stage at a time, completing all tasks in that stage before moving to the next
|
|
94
|
+
2. Mark each task complete by replacing `[ ]` with `[X]` as you finish it
|
|
95
|
+
3. Do NOT modify any other content in this file unless explicitly instructed by the user
|
|
96
|
+
4. Tasks without an `[X]` are not finished yet
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
- [ ] Currently working on this task
|
|
89
|
-
- [ ] Task being actively developed
|
|
98
|
+
---
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
- [
|
|
93
|
-
- [
|
|
100
|
+
### Stage 1: [Stage Name]
|
|
101
|
+
- [ ] Task description with clear action
|
|
102
|
+
- [ ] Another specific task to complete
|
|
94
103
|
|
|
95
|
-
|
|
96
|
-
- [ ] Task
|
|
104
|
+
### Stage 2: [Stage Name]
|
|
105
|
+
- [ ] Task in the next stage
|
|
106
|
+
- [ ] Another task in this stage
|
|
97
107
|
```
|
|
98
108
|
|
|
109
|
+
**IMPORTANT**:
|
|
110
|
+
- Group related tasks under numbered stages (Stage 1, Stage 2, etc.)
|
|
111
|
+
- Do NOT create separate "In Progress", "Done", or "Blocked" sections
|
|
112
|
+
- The `[ ]` / `[X]` checkboxes are the ONLY mechanism for tracking completion
|
|
113
|
+
- Each stage should be completable independently before moving to the next
|
|
114
|
+
|
|
99
115
|
## TASK CREATION PRINCIPLES
|
|
100
116
|
|
|
101
117
|
- **ALWAYS use checkbox format `[ ]` for every task**
|
|
@@ -145,6 +161,14 @@ INTEGRATION WITH RESEARCH & PLAN:
|
|
|
145
161
|
- Create validation/testing tasks for success criteria from plan
|
|
146
162
|
- Break down high-level plan steps into granular, executable tasks
|
|
147
163
|
|
|
164
|
+
PATH VERIFICATION (CRITICAL):
|
|
165
|
+
- Before generating tasks that reference specific file paths in `.shotgun/`, check the "Available Files" list in your System Status
|
|
166
|
+
- If specification.md references files under `.shotgun/contracts/` that don't appear in "Available Files", DO NOT generate tasks for those files
|
|
167
|
+
- The Specification agent is responsible for creating contract files, not downstream coding agents
|
|
168
|
+
- Tasks should reference files that EXIST or will be created in the project codebase (src/, tests/, etc.), not in `.shotgun/`
|
|
169
|
+
- Only generate tasks for `.shotgun/` files if they appear in the "Available Files" list and the task is about modifying them
|
|
170
|
+
- Do NOT generate tasks referencing `.shotgun/contracts/*` files unless those files already exist
|
|
171
|
+
|
|
148
172
|
IMPORTANT RULES:
|
|
149
173
|
- Make at most 1 tasks file write per request
|
|
150
174
|
- Always base tasks on available research and plan when relevant
|
shotgun/tui/app.py
CHANGED
|
@@ -13,6 +13,7 @@ from shotgun.agents.config import (
|
|
|
13
13
|
from shotgun.agents.models import AgentType
|
|
14
14
|
from shotgun.logging_config import get_logger
|
|
15
15
|
from shotgun.tui.containers import TUIContainer
|
|
16
|
+
from shotgun.tui.dependencies import create_default_router_deps
|
|
16
17
|
from shotgun.tui.screens.splash import SplashScreen
|
|
17
18
|
from shotgun.utils.file_system_utils import (
|
|
18
19
|
ensure_shotgun_directory_exists,
|
|
@@ -166,13 +167,11 @@ class ShotgunApp(App[None]):
|
|
|
166
167
|
return
|
|
167
168
|
|
|
168
169
|
# Create ChatScreen with all dependencies injected from container
|
|
169
|
-
# Get the default agent mode (
|
|
170
|
-
agent_mode = AgentType.
|
|
170
|
+
# Get the default agent mode (ROUTER)
|
|
171
|
+
agent_mode = AgentType.ROUTER
|
|
171
172
|
|
|
172
|
-
# Create
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
agent_deps = await create_default_tui_deps()
|
|
173
|
+
# Create RouterDeps asynchronously (get_provider_model is now async)
|
|
174
|
+
agent_deps = await create_default_router_deps()
|
|
176
175
|
|
|
177
176
|
# Create AgentManager with async initialization
|
|
178
177
|
agent_manager = AgentManager(deps=agent_deps, initial_type=agent_mode)
|
|
@@ -1,20 +1,68 @@
|
|
|
1
1
|
"""Widget to display the current agent mode."""
|
|
2
2
|
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
3
5
|
from textual.widget import Widget
|
|
4
6
|
|
|
5
7
|
from shotgun.agents.models import AgentType
|
|
6
|
-
from shotgun.
|
|
8
|
+
from shotgun.agents.router.models import RouterMode
|
|
9
|
+
from shotgun.tui.protocols import (
|
|
10
|
+
ActiveSubAgentProvider,
|
|
11
|
+
QAStateProvider,
|
|
12
|
+
RouterModeProvider,
|
|
13
|
+
)
|
|
7
14
|
from shotgun.tui.utils.mode_progress import PlaceholderHints
|
|
8
15
|
|
|
9
16
|
|
|
17
|
+
class RouterModeCssClass(StrEnum):
|
|
18
|
+
"""CSS class names for router mode styling."""
|
|
19
|
+
|
|
20
|
+
PLANNING = "mode-planning"
|
|
21
|
+
DRAFTING = "mode-drafting"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Shared display name mapping for agent types
|
|
25
|
+
AGENT_DISPLAY_NAMES: dict[AgentType, str] = {
|
|
26
|
+
AgentType.RESEARCH: "Research",
|
|
27
|
+
AgentType.SPECIFY: "Specify",
|
|
28
|
+
AgentType.PLAN: "Planning",
|
|
29
|
+
AgentType.TASKS: "Tasks",
|
|
30
|
+
AgentType.EXPORT: "Export",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Mode descriptions for legacy agent display
|
|
34
|
+
AGENT_DESCRIPTIONS: dict[AgentType, str] = {
|
|
35
|
+
AgentType.RESEARCH: "Research topics with web search and synthesize findings",
|
|
36
|
+
AgentType.PLAN: "Create comprehensive, actionable plans with milestones",
|
|
37
|
+
AgentType.TASKS: "Generate specific, actionable tasks from research and plans",
|
|
38
|
+
AgentType.SPECIFY: "Create detailed specifications and requirements documents",
|
|
39
|
+
AgentType.EXPORT: "Export artifacts and findings to various formats",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
10
43
|
class ModeIndicator(Widget):
|
|
11
|
-
"""Widget to display the current agent mode.
|
|
44
|
+
"""Widget to display the current agent mode.
|
|
45
|
+
|
|
46
|
+
For router mode, displays:
|
|
47
|
+
- Idle: "📋 Planning mode" or "✍️ Drafting mode"
|
|
48
|
+
- During execution: "📋 Planning → Research" format
|
|
49
|
+
|
|
50
|
+
For legacy agents, displays the agent name and description.
|
|
51
|
+
"""
|
|
12
52
|
|
|
13
53
|
DEFAULT_CSS = """
|
|
14
54
|
ModeIndicator {
|
|
15
55
|
text-wrap: wrap;
|
|
16
56
|
padding-left: 1;
|
|
17
57
|
}
|
|
58
|
+
|
|
59
|
+
ModeIndicator.mode-planning {
|
|
60
|
+
/* Planning mode styling - blue/cyan accent */
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
ModeIndicator.mode-drafting {
|
|
64
|
+
/* Drafting mode styling - green accent */
|
|
65
|
+
}
|
|
18
66
|
"""
|
|
19
67
|
|
|
20
68
|
def __init__(self, mode: AgentType) -> None:
|
|
@@ -29,41 +77,88 @@ class ModeIndicator(Widget):
|
|
|
29
77
|
|
|
30
78
|
def render(self) -> str:
|
|
31
79
|
"""Render the mode indicator."""
|
|
32
|
-
# Check if in Q&A mode first
|
|
80
|
+
# Check if in Q&A mode first - takes priority
|
|
33
81
|
if isinstance(self.screen, QAStateProvider) and self.screen.qa_mode:
|
|
34
82
|
return (
|
|
35
83
|
"[bold $text-accent]Q&A mode[/]"
|
|
36
84
|
"[$foreground-muted] (Answer the clarifying questions or ESC to cancel)[/]"
|
|
37
85
|
)
|
|
38
86
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
AgentType.TASKS: "Tasks",
|
|
43
|
-
AgentType.SPECIFY: "Specify",
|
|
44
|
-
AgentType.EXPORT: "Export",
|
|
45
|
-
}
|
|
46
|
-
mode_description = {
|
|
47
|
-
AgentType.RESEARCH: (
|
|
48
|
-
"Research topics with web search and synthesize findings"
|
|
49
|
-
),
|
|
50
|
-
AgentType.PLAN: "Create comprehensive, actionable plans with milestones",
|
|
51
|
-
AgentType.TASKS: (
|
|
52
|
-
"Generate specific, actionable tasks from research and plans"
|
|
53
|
-
),
|
|
54
|
-
AgentType.SPECIFY: (
|
|
55
|
-
"Create detailed specifications and requirements documents"
|
|
56
|
-
),
|
|
57
|
-
AgentType.EXPORT: "Export artifacts and findings to various formats",
|
|
58
|
-
}
|
|
87
|
+
# Router mode display
|
|
88
|
+
if self.mode == AgentType.ROUTER:
|
|
89
|
+
return self._render_router_mode()
|
|
59
90
|
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
# Legacy agent mode display
|
|
92
|
+
return self._render_legacy_mode()
|
|
93
|
+
|
|
94
|
+
def _render_router_mode(self) -> str:
|
|
95
|
+
"""Render the router mode indicator.
|
|
96
|
+
|
|
97
|
+
Shows:
|
|
98
|
+
- "📋 Planning mode" or "✍️ Drafting mode" when idle
|
|
99
|
+
- "📋 Planning → Research" format when sub-agent is executing
|
|
100
|
+
"""
|
|
101
|
+
# Get router mode from screen
|
|
102
|
+
router_mode: str | None = None
|
|
103
|
+
if isinstance(self.screen, RouterModeProvider):
|
|
104
|
+
router_mode = self.screen.router_mode
|
|
105
|
+
|
|
106
|
+
# Get active sub-agent from screen
|
|
107
|
+
active_sub_agent: AgentType | None = None
|
|
108
|
+
if isinstance(self.screen, ActiveSubAgentProvider):
|
|
109
|
+
sub_agent_str = self.screen.active_sub_agent
|
|
110
|
+
if sub_agent_str:
|
|
111
|
+
# Convert string back to AgentType enum
|
|
112
|
+
try:
|
|
113
|
+
active_sub_agent = AgentType(sub_agent_str)
|
|
114
|
+
except ValueError:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
# Determine mode display using RouterMode enum
|
|
118
|
+
if router_mode == RouterMode.DRAFTING.value:
|
|
119
|
+
icon = "✍️"
|
|
120
|
+
mode_name = "Drafting"
|
|
121
|
+
description = "Auto-execute without confirmation"
|
|
122
|
+
css_class = RouterModeCssClass.DRAFTING
|
|
123
|
+
else:
|
|
124
|
+
# Default to planning mode
|
|
125
|
+
icon = "📋"
|
|
126
|
+
mode_name = "Planning"
|
|
127
|
+
description = "Review plans before execution"
|
|
128
|
+
css_class = RouterModeCssClass.PLANNING
|
|
129
|
+
|
|
130
|
+
# Update CSS class for styling
|
|
131
|
+
self.set_classes(css_class)
|
|
132
|
+
|
|
133
|
+
# Add sub-agent suffix if executing
|
|
134
|
+
if active_sub_agent:
|
|
135
|
+
# Use shared display name mapping
|
|
136
|
+
sub_agent_name = AGENT_DISPLAY_NAMES.get(
|
|
137
|
+
active_sub_agent, active_sub_agent.value.title()
|
|
138
|
+
)
|
|
139
|
+
return f"[bold $text-accent]{icon} {mode_name} → {sub_agent_name}[/]"
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
f"[bold $text-accent]{icon} {mode_name} mode[/]"
|
|
143
|
+
f"[$foreground-muted] ({description})[/]"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def _render_legacy_mode(self) -> str:
|
|
147
|
+
"""Render the legacy agent mode indicator.
|
|
148
|
+
|
|
149
|
+
Shows the agent name with description and content status.
|
|
150
|
+
"""
|
|
151
|
+
mode_title = AGENT_DISPLAY_NAMES.get(self.mode, self.mode.value.title())
|
|
152
|
+
description = AGENT_DESCRIPTIONS.get(self.mode, "")
|
|
62
153
|
|
|
63
154
|
# Check if mode has content
|
|
64
155
|
has_content = self.progress_checker.has_mode_content(self.mode)
|
|
65
156
|
status_icon = " ✓" if has_content else ""
|
|
66
157
|
|
|
158
|
+
# Clear any router mode CSS classes
|
|
159
|
+
self.remove_class(RouterModeCssClass.PLANNING)
|
|
160
|
+
self.remove_class(RouterModeCssClass.DRAFTING)
|
|
161
|
+
|
|
67
162
|
return (
|
|
68
163
|
f"[bold $text-accent]{mode_title}{status_icon} mode[/]"
|
|
69
164
|
f"[$foreground-muted] ({description})[/]"
|
|
@@ -37,12 +37,12 @@ class StatusBar(Widget):
|
|
|
37
37
|
return (
|
|
38
38
|
"[$foreground-muted][bold $text]esc[/] to stop • "
|
|
39
39
|
"[bold $text]enter[/] to send • [bold $text]ctrl+j[/] for newline • "
|
|
40
|
-
"[bold $text]ctrl+p[/] command palette • [bold $text]shift+tab[/]
|
|
40
|
+
"[bold $text]ctrl+p[/] command palette • [bold $text]shift+tab[/] toggle mode • "
|
|
41
41
|
"/help for commands[/]"
|
|
42
42
|
)
|
|
43
43
|
else:
|
|
44
44
|
return (
|
|
45
45
|
"[$foreground-muted][bold $text]enter[/] to send • "
|
|
46
46
|
"[bold $text]ctrl+j[/] for newline • [bold $text]ctrl+p[/] command palette • "
|
|
47
|
-
"[bold $text]shift+tab[/]
|
|
47
|
+
"[bold $text]shift+tab[/] toggle mode • /help for commands[/]"
|
|
48
48
|
)
|
shotgun/tui/dependencies.py
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
"""Dependency creation utilities for TUI components."""
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
3
5
|
from pydantic_ai import RunContext
|
|
4
6
|
|
|
5
|
-
from shotgun.agents.config import get_provider_model
|
|
7
|
+
from shotgun.agents.config import get_config_manager, get_provider_model
|
|
8
|
+
from shotgun.agents.config.models import ModelConfig
|
|
6
9
|
from shotgun.agents.models import AgentDeps
|
|
10
|
+
from shotgun.agents.router.models import RouterDeps, RouterMode
|
|
11
|
+
from shotgun.codebase.service import CodebaseService
|
|
7
12
|
from shotgun.tui.filtered_codebase_service import FilteredCodebaseService
|
|
8
13
|
from shotgun.utils import get_shotgun_home
|
|
9
14
|
|
|
10
15
|
|
|
16
|
+
async def _get_tui_config() -> tuple[ModelConfig, CodebaseService]:
|
|
17
|
+
"""Get common TUI configuration components.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Tuple of (model_config, codebase_service) for TUI deps.
|
|
21
|
+
"""
|
|
22
|
+
model_config = await get_provider_model()
|
|
23
|
+
storage_dir = get_shotgun_home() / "codebases"
|
|
24
|
+
codebase_service = FilteredCodebaseService(storage_dir)
|
|
25
|
+
return model_config, codebase_service
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _placeholder_system_prompt_fn(ctx: RunContext[Any]) -> str:
|
|
29
|
+
"""Placeholder system prompt that should never be called.
|
|
30
|
+
|
|
31
|
+
Agents provide their own system_prompt_fn via their create functions.
|
|
32
|
+
This placeholder exists only to satisfy the AgentDeps requirement.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
RuntimeError: Always, as this should never be invoked.
|
|
36
|
+
"""
|
|
37
|
+
raise RuntimeError(
|
|
38
|
+
"This should not be called - agents provide their own system_prompt_fn"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
11
42
|
async def create_default_tui_deps() -> AgentDeps:
|
|
12
43
|
"""Create default AgentDeps for TUI components.
|
|
13
44
|
|
|
@@ -21,14 +52,7 @@ async def create_default_tui_deps() -> AgentDeps:
|
|
|
21
52
|
Returns:
|
|
22
53
|
Configured AgentDeps instance ready for TUI use.
|
|
23
54
|
"""
|
|
24
|
-
model_config = await
|
|
25
|
-
storage_dir = get_shotgun_home() / "codebases"
|
|
26
|
-
codebase_service = FilteredCodebaseService(storage_dir)
|
|
27
|
-
|
|
28
|
-
def _placeholder_system_prompt_fn(ctx: RunContext[AgentDeps]) -> str:
|
|
29
|
-
raise RuntimeError(
|
|
30
|
-
"This should not be called - agents provide their own system_prompt_fn"
|
|
31
|
-
)
|
|
55
|
+
model_config, codebase_service = await _get_tui_config()
|
|
32
56
|
|
|
33
57
|
return AgentDeps(
|
|
34
58
|
interactive_mode=True,
|
|
@@ -37,3 +61,34 @@ async def create_default_tui_deps() -> AgentDeps:
|
|
|
37
61
|
codebase_service=codebase_service,
|
|
38
62
|
system_prompt_fn=_placeholder_system_prompt_fn,
|
|
39
63
|
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async def create_default_router_deps() -> RouterDeps:
|
|
67
|
+
"""Create default RouterDeps for TUI components with router mode.
|
|
68
|
+
|
|
69
|
+
This creates a RouterDeps configuration suitable for interactive
|
|
70
|
+
TUI usage with:
|
|
71
|
+
- Router mode loaded from config (default: PLANNING)
|
|
72
|
+
- Interactive mode enabled
|
|
73
|
+
- TUI context flag set
|
|
74
|
+
- Filtered codebase service (restricted to CWD)
|
|
75
|
+
- Placeholder system prompt (router provides its own)
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Configured RouterDeps instance ready for TUI use.
|
|
79
|
+
"""
|
|
80
|
+
model_config, codebase_service = await _get_tui_config()
|
|
81
|
+
|
|
82
|
+
# Load router mode from config (default to PLANNING)
|
|
83
|
+
config_manager = get_config_manager()
|
|
84
|
+
config = await config_manager.load()
|
|
85
|
+
router_mode = RouterMode(config.router_mode)
|
|
86
|
+
|
|
87
|
+
return RouterDeps(
|
|
88
|
+
interactive_mode=True,
|
|
89
|
+
is_tui_context=True,
|
|
90
|
+
llm_model=model_config,
|
|
91
|
+
codebase_service=codebase_service,
|
|
92
|
+
system_prompt_fn=_placeholder_system_prompt_fn,
|
|
93
|
+
router_mode=router_mode,
|
|
94
|
+
)
|
shotgun/tui/protocols.py
CHANGED
|
@@ -43,3 +43,40 @@ class ProcessingStateProvider(Protocol):
|
|
|
43
43
|
True if an agent is processing, False otherwise.
|
|
44
44
|
"""
|
|
45
45
|
...
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@runtime_checkable
|
|
49
|
+
class RouterModeProvider(Protocol):
|
|
50
|
+
"""Protocol for screens that provide router mode state.
|
|
51
|
+
|
|
52
|
+
This protocol allows components to check the current router mode
|
|
53
|
+
(Planning or Drafting) without importing the concrete ChatScreen class.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def router_mode(self) -> str | None:
|
|
58
|
+
"""The current router mode.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
'planning' or 'drafting' if in router mode, None otherwise.
|
|
62
|
+
"""
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@runtime_checkable
|
|
67
|
+
class ActiveSubAgentProvider(Protocol):
|
|
68
|
+
"""Protocol for screens that provide active sub-agent state.
|
|
69
|
+
|
|
70
|
+
This protocol allows components to check which sub-agent is currently
|
|
71
|
+
executing during router delegation without importing ChatScreen.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def active_sub_agent(self) -> str | None:
|
|
76
|
+
"""The currently executing sub-agent type.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The sub-agent type string (e.g., 'research', 'specify') if
|
|
80
|
+
a sub-agent is executing, None if idle.
|
|
81
|
+
"""
|
|
82
|
+
...
|
|
@@ -16,11 +16,19 @@ ModeIndicator {
|
|
|
16
16
|
height: auto;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
ModeIndicator.mode-planning {
|
|
20
|
+
/* Blue/cyan accent for planning mode */
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
ModeIndicator.mode-drafting {
|
|
24
|
+
/* Green accent for drafting mode */
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
#footer {
|
|
20
28
|
dock: bottom;
|
|
21
29
|
height: auto;
|
|
22
30
|
padding: 1 1 1 2;
|
|
23
|
-
max-height:
|
|
31
|
+
max-height: 24;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
#window {
|