tunacode-cli 0.0.70__py3-none-any.whl → 0.0.78.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 tunacode-cli might be problematic. Click here for more details.
- tunacode/cli/commands/__init__.py +0 -2
- tunacode/cli/commands/implementations/__init__.py +0 -3
- tunacode/cli/commands/implementations/debug.py +2 -2
- tunacode/cli/commands/implementations/development.py +10 -8
- tunacode/cli/commands/implementations/model.py +357 -29
- tunacode/cli/commands/implementations/system.py +3 -2
- tunacode/cli/commands/implementations/template.py +0 -2
- tunacode/cli/commands/registry.py +8 -7
- tunacode/cli/commands/slash/loader.py +2 -1
- tunacode/cli/commands/slash/validator.py +2 -1
- tunacode/cli/main.py +19 -1
- tunacode/cli/repl.py +90 -229
- tunacode/cli/repl_components/command_parser.py +2 -1
- tunacode/cli/repl_components/error_recovery.py +8 -5
- tunacode/cli/repl_components/output_display.py +1 -10
- tunacode/cli/repl_components/tool_executor.py +1 -13
- tunacode/configuration/defaults.py +2 -2
- tunacode/configuration/key_descriptions.py +284 -0
- tunacode/configuration/settings.py +0 -1
- tunacode/constants.py +6 -42
- tunacode/core/agents/__init__.py +43 -2
- tunacode/core/agents/agent_components/__init__.py +7 -0
- tunacode/core/agents/agent_components/agent_config.py +162 -158
- tunacode/core/agents/agent_components/agent_helpers.py +31 -2
- tunacode/core/agents/agent_components/node_processor.py +180 -146
- tunacode/core/agents/agent_components/response_state.py +123 -6
- tunacode/core/agents/agent_components/state_transition.py +116 -0
- tunacode/core/agents/agent_components/streaming.py +296 -0
- tunacode/core/agents/agent_components/task_completion.py +19 -6
- tunacode/core/agents/agent_components/tool_buffer.py +21 -1
- tunacode/core/agents/agent_components/tool_executor.py +10 -0
- tunacode/core/agents/main.py +522 -370
- tunacode/core/agents/main_legact.py +538 -0
- tunacode/core/agents/prompts.py +66 -0
- tunacode/core/agents/utils.py +29 -122
- tunacode/core/setup/__init__.py +0 -2
- tunacode/core/setup/config_setup.py +88 -227
- tunacode/core/setup/config_wizard.py +230 -0
- tunacode/core/setup/coordinator.py +2 -1
- tunacode/core/state.py +16 -64
- tunacode/core/token_usage/usage_tracker.py +3 -1
- tunacode/core/tool_authorization.py +352 -0
- tunacode/core/tool_handler.py +67 -60
- tunacode/prompts/system.xml +751 -0
- tunacode/services/mcp.py +97 -1
- tunacode/setup.py +0 -23
- tunacode/tools/base.py +54 -1
- tunacode/tools/bash.py +14 -0
- tunacode/tools/glob.py +4 -2
- tunacode/tools/grep.py +7 -17
- tunacode/tools/prompts/glob_prompt.xml +1 -1
- tunacode/tools/prompts/grep_prompt.xml +1 -0
- tunacode/tools/prompts/list_dir_prompt.xml +1 -1
- tunacode/tools/prompts/react_prompt.xml +23 -0
- tunacode/tools/prompts/read_file_prompt.xml +1 -1
- tunacode/tools/react.py +153 -0
- tunacode/tools/run_command.py +15 -0
- tunacode/types.py +14 -79
- tunacode/ui/completers.py +434 -50
- tunacode/ui/config_dashboard.py +585 -0
- tunacode/ui/console.py +63 -11
- tunacode/ui/input.py +8 -3
- tunacode/ui/keybindings.py +0 -18
- tunacode/ui/model_selector.py +395 -0
- tunacode/ui/output.py +40 -19
- tunacode/ui/panels.py +173 -49
- tunacode/ui/path_heuristics.py +91 -0
- tunacode/ui/prompt_manager.py +1 -20
- tunacode/ui/tool_ui.py +30 -8
- tunacode/utils/api_key_validation.py +93 -0
- tunacode/utils/config_comparator.py +340 -0
- tunacode/utils/models_registry.py +593 -0
- tunacode/utils/text_utils.py +18 -1
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.78.6.dist-info}/METADATA +80 -12
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.78.6.dist-info}/RECORD +78 -74
- tunacode/cli/commands/implementations/plan.py +0 -50
- tunacode/cli/commands/implementations/todo.py +0 -217
- tunacode/context.py +0 -71
- tunacode/core/setup/git_safety_setup.py +0 -186
- tunacode/prompts/system.md +0 -359
- tunacode/prompts/system.md.bak +0 -487
- tunacode/tools/exit_plan_mode.py +0 -273
- tunacode/tools/present_plan.py +0 -288
- tunacode/tools/prompts/exit_plan_mode_prompt.xml +0 -25
- tunacode/tools/prompts/present_plan_prompt.xml +0 -20
- tunacode/tools/prompts/todo_prompt.xml +0 -96
- tunacode/tools/todo.py +0 -456
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.78.6.dist-info}/WHEEL +0 -0
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.78.6.dist-info}/entry_points.txt +0 -0
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.78.6.dist-info}/licenses/LICENSE +0 -0
tunacode/tools/exit_plan_mode.py
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
"""Tool for exiting plan mode and presenting implementation plan."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any, Dict, List
|
|
6
|
-
|
|
7
|
-
import defusedxml.ElementTree as ET
|
|
8
|
-
|
|
9
|
-
from tunacode.tools.base import BaseTool
|
|
10
|
-
from tunacode.types import ToolResult
|
|
11
|
-
from tunacode.ui import console as ui
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class ExitPlanModeTool(BaseTool):
|
|
17
|
-
"""Present implementation plan and exit plan mode."""
|
|
18
|
-
|
|
19
|
-
def __init__(self, state_manager, ui_logger=None):
|
|
20
|
-
"""Initialize the exit plan mode tool.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
state_manager: StateManager instance for controlling plan mode state
|
|
24
|
-
ui_logger: UI logger instance for displaying messages
|
|
25
|
-
"""
|
|
26
|
-
super().__init__(ui_logger)
|
|
27
|
-
self.state_manager = state_manager
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def tool_name(self) -> str:
|
|
31
|
-
return "exit_plan_mode"
|
|
32
|
-
|
|
33
|
-
def _get_base_prompt(self) -> str:
|
|
34
|
-
"""Load and return the base prompt from XML file.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
str: The loaded prompt from XML or a default prompt
|
|
38
|
-
"""
|
|
39
|
-
try:
|
|
40
|
-
# Load prompt from XML file
|
|
41
|
-
prompt_file = Path(__file__).parent / "prompts" / "exit_plan_mode_prompt.xml"
|
|
42
|
-
if prompt_file.exists():
|
|
43
|
-
tree = ET.parse(prompt_file)
|
|
44
|
-
root = tree.getroot()
|
|
45
|
-
description = root.find("description")
|
|
46
|
-
if description is not None:
|
|
47
|
-
return description.text.strip()
|
|
48
|
-
except Exception as e:
|
|
49
|
-
logger.warning(f"Failed to load XML prompt for exit_plan_mode: {e}")
|
|
50
|
-
|
|
51
|
-
# Fallback to default prompt
|
|
52
|
-
return """Use this tool when you have finished presenting your plan and are ready to code"""
|
|
53
|
-
|
|
54
|
-
def _get_parameters_schema(self) -> Dict[str, Any]:
|
|
55
|
-
"""Get the parameters schema for exit_plan_mode tool.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
Dict containing the JSON schema for tool parameters
|
|
59
|
-
"""
|
|
60
|
-
# Try to load from XML first
|
|
61
|
-
try:
|
|
62
|
-
prompt_file = Path(__file__).parent / "prompts" / "exit_plan_mode_prompt.xml"
|
|
63
|
-
if prompt_file.exists():
|
|
64
|
-
tree = ET.parse(prompt_file)
|
|
65
|
-
root = tree.getroot()
|
|
66
|
-
parameters = root.find("parameters")
|
|
67
|
-
if parameters is not None:
|
|
68
|
-
schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": []}
|
|
69
|
-
required_fields: List[str] = []
|
|
70
|
-
|
|
71
|
-
for param in parameters.findall("parameter"):
|
|
72
|
-
name = param.get("name")
|
|
73
|
-
required = param.get("required", "false").lower() == "true"
|
|
74
|
-
param_type = param.find("type")
|
|
75
|
-
description = param.find("description")
|
|
76
|
-
|
|
77
|
-
if name and param_type is not None:
|
|
78
|
-
prop = {
|
|
79
|
-
"type": param_type.text.strip(),
|
|
80
|
-
"description": description.text.strip()
|
|
81
|
-
if description is not None
|
|
82
|
-
else "",
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
schema["properties"][name] = prop
|
|
86
|
-
if required:
|
|
87
|
-
required_fields.append(name)
|
|
88
|
-
|
|
89
|
-
schema["required"] = required_fields
|
|
90
|
-
return schema
|
|
91
|
-
except Exception as e:
|
|
92
|
-
logger.warning(f"Failed to load parameters from XML for exit_plan_mode: {e}")
|
|
93
|
-
|
|
94
|
-
# Fallback to hardcoded schema
|
|
95
|
-
return {
|
|
96
|
-
"type": "object",
|
|
97
|
-
"properties": {
|
|
98
|
-
"plan": {
|
|
99
|
-
"type": "string",
|
|
100
|
-
"description": "The plan you came up with",
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
"required": ["plan"],
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async def _execute(
|
|
107
|
-
self,
|
|
108
|
-
plan_title: str,
|
|
109
|
-
overview: str,
|
|
110
|
-
implementation_steps: List[str],
|
|
111
|
-
files_to_modify: List[str] = None,
|
|
112
|
-
files_to_create: List[str] = None,
|
|
113
|
-
risks_and_considerations: List[str] = None,
|
|
114
|
-
testing_approach: str = None,
|
|
115
|
-
success_criteria: List[str] = None,
|
|
116
|
-
) -> ToolResult:
|
|
117
|
-
"""Present the implementation plan and get user approval."""
|
|
118
|
-
|
|
119
|
-
plan = {
|
|
120
|
-
"title": plan_title,
|
|
121
|
-
"overview": overview,
|
|
122
|
-
"files_to_modify": files_to_modify or [],
|
|
123
|
-
"files_to_create": files_to_create or [],
|
|
124
|
-
"implementation_steps": implementation_steps,
|
|
125
|
-
"risks_and_considerations": risks_and_considerations or [],
|
|
126
|
-
"testing_approach": testing_approach or "Manual testing of functionality",
|
|
127
|
-
"success_criteria": success_criteria or [],
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
# Present plan to user
|
|
131
|
-
await self._present_plan(plan)
|
|
132
|
-
|
|
133
|
-
# Get user approval
|
|
134
|
-
approved = await self._get_user_approval()
|
|
135
|
-
|
|
136
|
-
# Update state based on user approval
|
|
137
|
-
if approved:
|
|
138
|
-
# Store the plan and exit plan mode
|
|
139
|
-
self.state_manager.set_current_plan(plan)
|
|
140
|
-
self.state_manager.exit_plan_mode(plan)
|
|
141
|
-
await ui.success("✅ Plan approved! Exiting Plan Mode.")
|
|
142
|
-
return "Plan approved and Plan Mode exited. You can now execute the implementation using write tools (write_file, update_file, bash, run_command)."
|
|
143
|
-
else:
|
|
144
|
-
# Keep the plan but stay in plan mode
|
|
145
|
-
self.state_manager.set_current_plan(plan)
|
|
146
|
-
await ui.warning("❌ Plan rejected. Staying in Plan Mode for further research.")
|
|
147
|
-
return "Plan rejected. Continue researching and refine your approach. You remain in Plan Mode - only read-only tools are available."
|
|
148
|
-
|
|
149
|
-
async def _present_plan(self, plan: Dict[str, Any]) -> None:
|
|
150
|
-
"""Present the plan in a formatted way."""
|
|
151
|
-
# Build the entire plan output as a single string to avoid UI flooding
|
|
152
|
-
output = []
|
|
153
|
-
output.append("")
|
|
154
|
-
output.append("╭─────────────────────────────────────────────────────────╮")
|
|
155
|
-
output.append("│ 📋 IMPLEMENTATION PLAN │")
|
|
156
|
-
output.append("╰─────────────────────────────────────────────────────────╯")
|
|
157
|
-
output.append("")
|
|
158
|
-
output.append(f"🎯 {plan['title']}")
|
|
159
|
-
output.append("")
|
|
160
|
-
|
|
161
|
-
if plan["overview"]:
|
|
162
|
-
output.append(f"📝 Overview: {plan['overview']}")
|
|
163
|
-
output.append("")
|
|
164
|
-
|
|
165
|
-
# Files section
|
|
166
|
-
if plan["files_to_modify"]:
|
|
167
|
-
output.append("📝 Files to Modify:")
|
|
168
|
-
for f in plan["files_to_modify"]:
|
|
169
|
-
output.append(f" • {f}")
|
|
170
|
-
output.append("")
|
|
171
|
-
|
|
172
|
-
if plan["files_to_create"]:
|
|
173
|
-
output.append("📄 Files to Create:")
|
|
174
|
-
for f in plan["files_to_create"]:
|
|
175
|
-
output.append(f" • {f}")
|
|
176
|
-
output.append("")
|
|
177
|
-
|
|
178
|
-
# Implementation steps
|
|
179
|
-
output.append("🔧 Implementation Steps:")
|
|
180
|
-
for i, step in enumerate(plan["implementation_steps"], 1):
|
|
181
|
-
output.append(f" {i}. {step}")
|
|
182
|
-
output.append("")
|
|
183
|
-
|
|
184
|
-
# Testing approach
|
|
185
|
-
if plan["testing_approach"]:
|
|
186
|
-
output.append(f"🧪 Testing Approach: {plan['testing_approach']}")
|
|
187
|
-
output.append("")
|
|
188
|
-
|
|
189
|
-
# Success criteria
|
|
190
|
-
if plan["success_criteria"]:
|
|
191
|
-
output.append("✅ Success Criteria:")
|
|
192
|
-
for criteria in plan["success_criteria"]:
|
|
193
|
-
output.append(f" • {criteria}")
|
|
194
|
-
output.append("")
|
|
195
|
-
|
|
196
|
-
# Risks and considerations
|
|
197
|
-
if plan["risks_and_considerations"]:
|
|
198
|
-
output.append("⚠️ Risks & Considerations:")
|
|
199
|
-
for risk in plan["risks_and_considerations"]:
|
|
200
|
-
output.append(f" • {risk}")
|
|
201
|
-
output.append("")
|
|
202
|
-
|
|
203
|
-
# Print everything at once
|
|
204
|
-
await ui.info("\n".join(output))
|
|
205
|
-
|
|
206
|
-
async def _get_user_approval(self) -> bool:
|
|
207
|
-
"""Get user approval for the plan."""
|
|
208
|
-
try:
|
|
209
|
-
from prompt_toolkit import PromptSession
|
|
210
|
-
from prompt_toolkit.patch_stdout import patch_stdout
|
|
211
|
-
|
|
212
|
-
session = PromptSession()
|
|
213
|
-
|
|
214
|
-
with patch_stdout():
|
|
215
|
-
response = await session.prompt_async(
|
|
216
|
-
"\n🤔 Approve this implementation plan? (y/n): "
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
return response.strip().lower() in ["y", "yes", "approve"]
|
|
220
|
-
except (KeyboardInterrupt, EOFError):
|
|
221
|
-
return False
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def create_exit_plan_mode_tool(state_manager):
|
|
225
|
-
"""
|
|
226
|
-
Factory function to create exit_plan_mode tool with the correct state manager.
|
|
227
|
-
|
|
228
|
-
Args:
|
|
229
|
-
state_manager: The StateManager instance to use
|
|
230
|
-
|
|
231
|
-
Returns:
|
|
232
|
-
Callable: The exit_plan_mode function bound to the provided state manager
|
|
233
|
-
"""
|
|
234
|
-
|
|
235
|
-
async def exit_plan_mode(
|
|
236
|
-
plan_title: str,
|
|
237
|
-
overview: str,
|
|
238
|
-
implementation_steps: List[str],
|
|
239
|
-
files_to_modify: List[str] = None,
|
|
240
|
-
files_to_create: List[str] = None,
|
|
241
|
-
risks_and_considerations: List[str] = None,
|
|
242
|
-
testing_approach: str = None,
|
|
243
|
-
success_criteria: List[str] = None,
|
|
244
|
-
) -> str:
|
|
245
|
-
"""
|
|
246
|
-
Present implementation plan and exit plan mode.
|
|
247
|
-
|
|
248
|
-
Args:
|
|
249
|
-
plan_title: Brief title for the implementation plan
|
|
250
|
-
overview: High-level overview of the changes needed
|
|
251
|
-
implementation_steps: Ordered list of implementation steps
|
|
252
|
-
files_to_modify: List of files that need to be modified
|
|
253
|
-
files_to_create: List of new files to be created
|
|
254
|
-
risks_and_considerations: Potential risks or important considerations
|
|
255
|
-
testing_approach: Approach for testing the implementation
|
|
256
|
-
success_criteria: Criteria for considering the implementation successful
|
|
257
|
-
|
|
258
|
-
Returns:
|
|
259
|
-
str: Result message indicating plan approval status
|
|
260
|
-
"""
|
|
261
|
-
tool = ExitPlanModeTool(state_manager=state_manager)
|
|
262
|
-
return await tool._execute(
|
|
263
|
-
plan_title=plan_title,
|
|
264
|
-
overview=overview,
|
|
265
|
-
implementation_steps=implementation_steps,
|
|
266
|
-
files_to_modify=files_to_modify,
|
|
267
|
-
files_to_create=files_to_create,
|
|
268
|
-
risks_and_considerations=risks_and_considerations,
|
|
269
|
-
testing_approach=testing_approach,
|
|
270
|
-
success_criteria=success_criteria,
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
return exit_plan_mode
|
tunacode/tools/present_plan.py
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
"""Tool for presenting a structured plan and exiting plan mode."""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any, Dict, List, Optional
|
|
6
|
-
|
|
7
|
-
import defusedxml.ElementTree as ET
|
|
8
|
-
|
|
9
|
-
from tunacode.tools.base import BaseTool
|
|
10
|
-
from tunacode.types import PlanDoc, PlanPhase, ToolResult
|
|
11
|
-
from tunacode.ui import console as ui
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class PresentPlanTool(BaseTool):
|
|
17
|
-
"""Present a structured implementation plan and request user approval."""
|
|
18
|
-
|
|
19
|
-
def __init__(self, state_manager, ui_logger=None):
|
|
20
|
-
"""Initialize the present plan tool.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
state_manager: StateManager instance for controlling plan mode state
|
|
24
|
-
ui_logger: UI logger instance for displaying messages
|
|
25
|
-
"""
|
|
26
|
-
super().__init__(ui_logger)
|
|
27
|
-
self.state_manager = state_manager
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def tool_name(self) -> str:
|
|
31
|
-
return "present_plan"
|
|
32
|
-
|
|
33
|
-
def _get_base_prompt(self) -> str:
|
|
34
|
-
"""Load and return the base prompt from XML file.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
str: The loaded prompt from XML or a default prompt
|
|
38
|
-
"""
|
|
39
|
-
try:
|
|
40
|
-
# Load prompt from XML file
|
|
41
|
-
prompt_file = Path(__file__).parent / "prompts" / "present_plan_prompt.xml"
|
|
42
|
-
if prompt_file.exists():
|
|
43
|
-
tree = ET.parse(prompt_file)
|
|
44
|
-
root = tree.getroot()
|
|
45
|
-
description = root.find("description")
|
|
46
|
-
if description is not None:
|
|
47
|
-
return description.text.strip()
|
|
48
|
-
except Exception as e:
|
|
49
|
-
logger.warning(f"Failed to load XML prompt for present_plan: {e}")
|
|
50
|
-
|
|
51
|
-
# Fallback to default prompt
|
|
52
|
-
return """Present a plan to the user for approval before execution"""
|
|
53
|
-
|
|
54
|
-
def _get_parameters_schema(self) -> Dict[str, Any]:
|
|
55
|
-
"""Get the parameters schema for present_plan tool.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
Dict containing the JSON schema for tool parameters
|
|
59
|
-
"""
|
|
60
|
-
# Try to load from XML first
|
|
61
|
-
try:
|
|
62
|
-
prompt_file = Path(__file__).parent / "prompts" / "present_plan_prompt.xml"
|
|
63
|
-
if prompt_file.exists():
|
|
64
|
-
tree = ET.parse(prompt_file)
|
|
65
|
-
root = tree.getroot()
|
|
66
|
-
parameters = root.find("parameters")
|
|
67
|
-
if parameters is not None:
|
|
68
|
-
schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": []}
|
|
69
|
-
required_fields: List[str] = []
|
|
70
|
-
|
|
71
|
-
for param in parameters.findall("parameter"):
|
|
72
|
-
name = param.get("name")
|
|
73
|
-
required = param.get("required", "false").lower() == "true"
|
|
74
|
-
param_type = param.find("type")
|
|
75
|
-
description = param.find("description")
|
|
76
|
-
|
|
77
|
-
if name and param_type is not None:
|
|
78
|
-
prop = {
|
|
79
|
-
"type": param_type.text.strip(),
|
|
80
|
-
"description": description.text.strip()
|
|
81
|
-
if description is not None
|
|
82
|
-
else "",
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
schema["properties"][name] = prop
|
|
86
|
-
if required:
|
|
87
|
-
required_fields.append(name)
|
|
88
|
-
|
|
89
|
-
schema["required"] = required_fields
|
|
90
|
-
return schema
|
|
91
|
-
except Exception as e:
|
|
92
|
-
logger.warning(f"Failed to load parameters from XML for present_plan: {e}")
|
|
93
|
-
|
|
94
|
-
# Fallback to hardcoded schema
|
|
95
|
-
return {
|
|
96
|
-
"type": "object",
|
|
97
|
-
"properties": {
|
|
98
|
-
"plan": {
|
|
99
|
-
"type": "string",
|
|
100
|
-
"description": "The plan to present to the user",
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
"required": ["plan"],
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async def _execute(
|
|
107
|
-
self,
|
|
108
|
-
title: str,
|
|
109
|
-
overview: str,
|
|
110
|
-
steps: List[str],
|
|
111
|
-
files_to_modify: List[str] = None,
|
|
112
|
-
files_to_create: List[str] = None,
|
|
113
|
-
risks: List[str] = None,
|
|
114
|
-
tests: List[str] = None,
|
|
115
|
-
rollback: Optional[str] = None,
|
|
116
|
-
open_questions: List[str] = None,
|
|
117
|
-
success_criteria: List[str] = None,
|
|
118
|
-
references: List[str] = None,
|
|
119
|
-
) -> ToolResult:
|
|
120
|
-
"""Present the implementation plan for user approval."""
|
|
121
|
-
|
|
122
|
-
# Create PlanDoc from parameters
|
|
123
|
-
plan_doc = PlanDoc(
|
|
124
|
-
title=title,
|
|
125
|
-
overview=overview,
|
|
126
|
-
steps=steps,
|
|
127
|
-
files_to_modify=files_to_modify or [],
|
|
128
|
-
files_to_create=files_to_create or [],
|
|
129
|
-
risks=risks or [],
|
|
130
|
-
tests=tests or [],
|
|
131
|
-
rollback=rollback,
|
|
132
|
-
open_questions=open_questions or [],
|
|
133
|
-
success_criteria=success_criteria or [],
|
|
134
|
-
references=references or [],
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
# Validate the plan
|
|
138
|
-
is_valid, missing_sections = plan_doc.validate()
|
|
139
|
-
if not is_valid:
|
|
140
|
-
return f"❌ Plan incomplete. Missing sections: {', '.join(missing_sections)}. Continue researching and refining your plan."
|
|
141
|
-
|
|
142
|
-
# Set plan phase to PLAN_READY and store the plan
|
|
143
|
-
# The REPL will handle displaying the plan when it detects PLAN_READY phase
|
|
144
|
-
self.state_manager.session.plan_phase = PlanPhase.PLAN_READY
|
|
145
|
-
self.state_manager.session.current_plan = plan_doc
|
|
146
|
-
|
|
147
|
-
return "Plan ready for review. The system will now present it to the user for approval."
|
|
148
|
-
|
|
149
|
-
async def _present_plan(self, plan_doc: PlanDoc) -> None:
|
|
150
|
-
"""Present the plan in a formatted way."""
|
|
151
|
-
output = []
|
|
152
|
-
output.append("")
|
|
153
|
-
output.append("╭─────────────────────────────────────────────────────────╮")
|
|
154
|
-
output.append("│ 📋 IMPLEMENTATION PLAN │")
|
|
155
|
-
output.append("╰─────────────────────────────────────────────────────────╯")
|
|
156
|
-
output.append("")
|
|
157
|
-
output.append(f"🎯 **{plan_doc.title}**")
|
|
158
|
-
output.append("")
|
|
159
|
-
|
|
160
|
-
if plan_doc.overview:
|
|
161
|
-
output.append(f"📝 **Overview:** {plan_doc.overview}")
|
|
162
|
-
output.append("")
|
|
163
|
-
|
|
164
|
-
# Files section
|
|
165
|
-
if plan_doc.files_to_modify:
|
|
166
|
-
output.append("📝 **Files to Modify:**")
|
|
167
|
-
for f in plan_doc.files_to_modify:
|
|
168
|
-
output.append(f" • {f}")
|
|
169
|
-
output.append("")
|
|
170
|
-
|
|
171
|
-
if plan_doc.files_to_create:
|
|
172
|
-
output.append("📄 **Files to Create:**")
|
|
173
|
-
for f in plan_doc.files_to_create:
|
|
174
|
-
output.append(f" • {f}")
|
|
175
|
-
output.append("")
|
|
176
|
-
|
|
177
|
-
# Implementation steps
|
|
178
|
-
output.append("🔧 **Implementation Steps:**")
|
|
179
|
-
for i, step in enumerate(plan_doc.steps, 1):
|
|
180
|
-
output.append(f" {i}. {step}")
|
|
181
|
-
output.append("")
|
|
182
|
-
|
|
183
|
-
# Testing approach
|
|
184
|
-
if plan_doc.tests:
|
|
185
|
-
output.append("🧪 **Testing Approach:**")
|
|
186
|
-
for test in plan_doc.tests:
|
|
187
|
-
output.append(f" • {test}")
|
|
188
|
-
output.append("")
|
|
189
|
-
|
|
190
|
-
# Success criteria
|
|
191
|
-
if plan_doc.success_criteria:
|
|
192
|
-
output.append("✅ **Success Criteria:**")
|
|
193
|
-
for criteria in plan_doc.success_criteria:
|
|
194
|
-
output.append(f" • {criteria}")
|
|
195
|
-
output.append("")
|
|
196
|
-
|
|
197
|
-
# Risks and considerations
|
|
198
|
-
if plan_doc.risks:
|
|
199
|
-
output.append("⚠️ **Risks & Considerations:**")
|
|
200
|
-
for risk in plan_doc.risks:
|
|
201
|
-
output.append(f" • {risk}")
|
|
202
|
-
output.append("")
|
|
203
|
-
|
|
204
|
-
# Open questions
|
|
205
|
-
if plan_doc.open_questions:
|
|
206
|
-
output.append("❓ **Open Questions:**")
|
|
207
|
-
for question in plan_doc.open_questions:
|
|
208
|
-
output.append(f" • {question}")
|
|
209
|
-
output.append("")
|
|
210
|
-
|
|
211
|
-
# References
|
|
212
|
-
if plan_doc.references:
|
|
213
|
-
output.append("📚 **References:**")
|
|
214
|
-
for ref in plan_doc.references:
|
|
215
|
-
output.append(f" • {ref}")
|
|
216
|
-
output.append("")
|
|
217
|
-
|
|
218
|
-
# Rollback plan
|
|
219
|
-
if plan_doc.rollback:
|
|
220
|
-
output.append(f"🔄 **Rollback Plan:** {plan_doc.rollback}")
|
|
221
|
-
output.append("")
|
|
222
|
-
|
|
223
|
-
# Print everything at once
|
|
224
|
-
await ui.info("\n".join(output))
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def create_present_plan_tool(state_manager):
|
|
228
|
-
"""
|
|
229
|
-
Factory function to create present_plan tool with the correct state manager.
|
|
230
|
-
|
|
231
|
-
Args:
|
|
232
|
-
state_manager: The StateManager instance to use
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
Callable: The present_plan function bound to the provided state manager
|
|
236
|
-
"""
|
|
237
|
-
|
|
238
|
-
async def present_plan(
|
|
239
|
-
title: str,
|
|
240
|
-
overview: str,
|
|
241
|
-
steps: List[str],
|
|
242
|
-
files_to_modify: List[str] = None,
|
|
243
|
-
files_to_create: List[str] = None,
|
|
244
|
-
risks: List[str] = None,
|
|
245
|
-
tests: List[str] = None,
|
|
246
|
-
rollback: Optional[str] = None,
|
|
247
|
-
open_questions: List[str] = None,
|
|
248
|
-
success_criteria: List[str] = None,
|
|
249
|
-
references: List[str] = None,
|
|
250
|
-
) -> str:
|
|
251
|
-
"""
|
|
252
|
-
Present a structured implementation plan for user approval.
|
|
253
|
-
|
|
254
|
-
This tool should ONLY be called when you have a complete, well-researched plan.
|
|
255
|
-
All required sections must be filled out before calling this tool.
|
|
256
|
-
|
|
257
|
-
Args:
|
|
258
|
-
title: Brief, descriptive title for the implementation plan
|
|
259
|
-
overview: High-level summary of what needs to be implemented and why
|
|
260
|
-
steps: Ordered list of specific implementation steps (required)
|
|
261
|
-
files_to_modify: List of existing files that need to be modified
|
|
262
|
-
files_to_create: List of new files that need to be created
|
|
263
|
-
risks: Potential risks, challenges, or considerations
|
|
264
|
-
tests: Testing approach and test cases to validate implementation
|
|
265
|
-
rollback: Plan for reverting changes if needed
|
|
266
|
-
open_questions: Any remaining questions or uncertainties
|
|
267
|
-
success_criteria: Specific criteria for considering the task complete
|
|
268
|
-
references: External resources, documentation, or research sources
|
|
269
|
-
|
|
270
|
-
Returns:
|
|
271
|
-
str: Status message about plan presentation
|
|
272
|
-
"""
|
|
273
|
-
tool = PresentPlanTool(state_manager=state_manager)
|
|
274
|
-
return await tool._execute(
|
|
275
|
-
title=title,
|
|
276
|
-
overview=overview,
|
|
277
|
-
steps=steps,
|
|
278
|
-
files_to_modify=files_to_modify,
|
|
279
|
-
files_to_create=files_to_create,
|
|
280
|
-
risks=risks,
|
|
281
|
-
tests=tests,
|
|
282
|
-
rollback=rollback,
|
|
283
|
-
open_questions=open_questions,
|
|
284
|
-
success_criteria=success_criteria,
|
|
285
|
-
references=references,
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
return present_plan
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<tool_prompt>
|
|
3
|
-
<description>
|
|
4
|
-
Use this tool when you are in plan mode and have finished presenting your plan and are ready to code. This will prompt the user to exit plan mode.
|
|
5
|
-
IMPORTANT: Only use this tool when the task requires planning the implementation steps of a task that requires writing code. For research tasks where you're gathering information, searching files, reading files or in general trying to understand the codebase - do NOT use this tool.
|
|
6
|
-
|
|
7
|
-
Eg.
|
|
8
|
-
1. Initial task: "Search for and understand the implementation of vim mode in the codebase" - Do not use the exit plan mode tool because you are not planning the implementation steps of a task.
|
|
9
|
-
2. Initial task: "Help me implement yank mode for vim" - Use the exit plan mode tool after you have finished planning the implementation steps of the task.
|
|
10
|
-
</description>
|
|
11
|
-
|
|
12
|
-
<parameters>
|
|
13
|
-
<parameter name="plan" required="true">
|
|
14
|
-
<description>The plan you came up with, that you want to run by the user for approval. Supports markdown. The plan should be pretty concise.</description>
|
|
15
|
-
<type>string</type>
|
|
16
|
-
</parameter>
|
|
17
|
-
</parameters>
|
|
18
|
-
|
|
19
|
-
<examples>
|
|
20
|
-
<example>
|
|
21
|
-
<title>Exit plan mode with implementation plan</title>
|
|
22
|
-
<command>{"plan": "## Implementation Plan\n\n1. Create authentication middleware\n2. Add user model and database schema\n3. Implement login/logout endpoints\n4. Add session management\n5. Write tests for authentication flow"}</command>
|
|
23
|
-
</example>
|
|
24
|
-
</examples>
|
|
25
|
-
</tool_prompt>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<tool_prompt>
|
|
3
|
-
<description>
|
|
4
|
-
Present a plan to the user for approval before execution. This tool is used when you need to outline a series of steps or actions you intend to take, allowing the user to review and approve the plan before proceeding.
|
|
5
|
-
</description>
|
|
6
|
-
|
|
7
|
-
<parameters>
|
|
8
|
-
<parameter name="plan" required="true">
|
|
9
|
-
<description>The plan to present to the user, formatted in markdown</description>
|
|
10
|
-
<type>string</type>
|
|
11
|
-
</parameter>
|
|
12
|
-
</parameters>
|
|
13
|
-
|
|
14
|
-
<examples>
|
|
15
|
-
<example>
|
|
16
|
-
<title>Present a refactoring plan</title>
|
|
17
|
-
<command>{"plan": "## Refactoring Plan\n\n1. **Extract common logic** - Move duplicated code to utility functions\n2. **Update imports** - Adjust all import statements\n3. **Run tests** - Ensure no functionality is broken\n4. **Update documentation** - Reflect the new structure"}</command>
|
|
18
|
-
</example>
|
|
19
|
-
</examples>
|
|
20
|
-
</tool_prompt>
|