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/context.py
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import subprocess
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Dict, List
|
|
5
|
-
|
|
6
|
-
from tunacode.utils.ripgrep import ripgrep
|
|
7
|
-
from tunacode.utils.system import list_cwd
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
async def get_git_status() -> Dict[str, object]:
|
|
13
|
-
"""Return git branch and dirty state information."""
|
|
14
|
-
try:
|
|
15
|
-
result = subprocess.run(
|
|
16
|
-
["git", "status", "--porcelain", "--branch"],
|
|
17
|
-
capture_output=True,
|
|
18
|
-
text=True,
|
|
19
|
-
check=True,
|
|
20
|
-
timeout=5,
|
|
21
|
-
)
|
|
22
|
-
lines = result.stdout.splitlines()
|
|
23
|
-
branch_line = lines[0][2:] if lines else ""
|
|
24
|
-
branch = branch_line.split("...")[0]
|
|
25
|
-
ahead = behind = 0
|
|
26
|
-
if "[" in branch_line and "]" in branch_line:
|
|
27
|
-
bracket = branch_line.split("[", 1)[1].split("]", 1)[0]
|
|
28
|
-
for part in bracket.split(","):
|
|
29
|
-
if "ahead" in part:
|
|
30
|
-
ahead = int(part.split("ahead")[1].strip().strip(" ]"))
|
|
31
|
-
if "behind" in part:
|
|
32
|
-
behind = int(part.split("behind")[1].strip().strip(" ]"))
|
|
33
|
-
dirty = any(line for line in lines[1:])
|
|
34
|
-
return {"branch": branch, "ahead": ahead, "behind": behind, "dirty": dirty}
|
|
35
|
-
except Exception as e:
|
|
36
|
-
logger.warning(f"Failed to get git status: {e}")
|
|
37
|
-
return {}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
async def get_directory_structure(max_depth: int = 3) -> str:
|
|
41
|
-
"""Return a simple directory tree string."""
|
|
42
|
-
files = list_cwd(max_depth=max_depth)
|
|
43
|
-
lines: List[str] = []
|
|
44
|
-
for path in files:
|
|
45
|
-
depth = path.count("/")
|
|
46
|
-
indent = " " * depth
|
|
47
|
-
name = path.split("/")[-1]
|
|
48
|
-
lines.append(f"{indent}{name}")
|
|
49
|
-
return "\n".join(lines)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
async def get_code_style() -> str:
|
|
53
|
-
"""Concatenate contents of all TUNACODE.md files up the directory tree."""
|
|
54
|
-
parts: List[str] = []
|
|
55
|
-
current = Path.cwd()
|
|
56
|
-
while True:
|
|
57
|
-
file = current / "TUNACODE.md"
|
|
58
|
-
if file.exists():
|
|
59
|
-
try:
|
|
60
|
-
parts.append(file.read_text(encoding="utf-8"))
|
|
61
|
-
except Exception as e:
|
|
62
|
-
logger.debug(f"Failed to read TUNACODE.md at {file}: {e}")
|
|
63
|
-
if current == current.parent:
|
|
64
|
-
break
|
|
65
|
-
current = current.parent
|
|
66
|
-
return "\n".join(parts)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
async def get_claude_files() -> List[str]:
|
|
70
|
-
"""Return a list of additional TUNACODE.md files in the repo."""
|
|
71
|
-
return ripgrep("TUNACODE.md", ".")
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
"""Git safety setup to create a working branch for TunaCode."""
|
|
2
|
-
|
|
3
|
-
import subprocess
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
from tunacode.core.setup.base import BaseSetup
|
|
7
|
-
from tunacode.core.state import StateManager
|
|
8
|
-
from tunacode.ui import console as ui
|
|
9
|
-
from tunacode.ui.input import input as prompt_input
|
|
10
|
-
from tunacode.ui.panels import panel
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
async def yes_no_prompt(question: str, default: bool = True) -> bool:
|
|
14
|
-
"""Simple yes/no prompt."""
|
|
15
|
-
default_text = "[Y/n]" if default else "[y/N]"
|
|
16
|
-
response = await prompt_input(session_key="yes_no", pretext=f"{question} {default_text}: ")
|
|
17
|
-
|
|
18
|
-
if not response.strip():
|
|
19
|
-
return default
|
|
20
|
-
|
|
21
|
-
return response.lower().strip() in ["y", "yes"]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class GitSafetySetup(BaseSetup):
|
|
25
|
-
"""Setup step to create a safe working branch for TunaCode."""
|
|
26
|
-
|
|
27
|
-
def __init__(self, state_manager: StateManager):
|
|
28
|
-
super().__init__(state_manager)
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def name(self) -> str:
|
|
32
|
-
"""Return the name of this setup step."""
|
|
33
|
-
return "Git Safety"
|
|
34
|
-
|
|
35
|
-
async def should_run(self, _force: bool = False) -> bool:
|
|
36
|
-
"""Check if we should run git safety setup."""
|
|
37
|
-
# Always run unless user has explicitly disabled it
|
|
38
|
-
return not self.state_manager.session.user_config.get("skip_git_safety", False)
|
|
39
|
-
|
|
40
|
-
async def execute(self, _force: bool = False, wizard_mode: bool = False) -> None:
|
|
41
|
-
"""Create a safety branch for TunaCode operations."""
|
|
42
|
-
# Skip git safety during wizard mode to avoid UI interference
|
|
43
|
-
if wizard_mode:
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
# Check if git is installed
|
|
48
|
-
result = subprocess.run(
|
|
49
|
-
["git", "--version"], capture_output=True, text=True, check=False
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
if result.returncode != 0:
|
|
53
|
-
await panel(
|
|
54
|
-
" Git Not Found",
|
|
55
|
-
"Git is not installed or not in PATH. TunaCode will modify files directly.\n"
|
|
56
|
-
"It's strongly recommended to install Git for safety.",
|
|
57
|
-
border_style="yellow",
|
|
58
|
-
)
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
# Check if we're in a git repository
|
|
62
|
-
result = subprocess.run(
|
|
63
|
-
["git", "rev-parse", "--git-dir"],
|
|
64
|
-
capture_output=True,
|
|
65
|
-
text=True,
|
|
66
|
-
check=False,
|
|
67
|
-
cwd=Path.cwd(),
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
if result.returncode != 0:
|
|
71
|
-
await panel(
|
|
72
|
-
" Not a Git Repository",
|
|
73
|
-
"This directory is not a Git repository. TunaCode will modify files directly.\n"
|
|
74
|
-
"Consider initializing a Git repository for safety: git init",
|
|
75
|
-
border_style="yellow",
|
|
76
|
-
)
|
|
77
|
-
return
|
|
78
|
-
|
|
79
|
-
# Get current branch name
|
|
80
|
-
result = subprocess.run(
|
|
81
|
-
["git", "branch", "--show-current"], capture_output=True, text=True, check=True
|
|
82
|
-
)
|
|
83
|
-
current_branch = result.stdout.strip()
|
|
84
|
-
|
|
85
|
-
if not current_branch:
|
|
86
|
-
# Detached HEAD state
|
|
87
|
-
await panel(
|
|
88
|
-
" Detached HEAD State",
|
|
89
|
-
"You're in a detached HEAD state. TunaCode will continue without creating a branch.",
|
|
90
|
-
border_style="yellow",
|
|
91
|
-
)
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
# Check if we're already on a -tunacode branch
|
|
95
|
-
if current_branch.endswith("-tunacode"):
|
|
96
|
-
await ui.info(f"Already on a TunaCode branch: {current_branch}")
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
# Propose new branch name
|
|
100
|
-
new_branch = f"{current_branch}-tunacode"
|
|
101
|
-
|
|
102
|
-
# Check if there are uncommitted changes
|
|
103
|
-
result = subprocess.run(
|
|
104
|
-
["git", "status", "--porcelain"], capture_output=True, text=True, check=True
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
has_changes = bool(result.stdout.strip())
|
|
108
|
-
|
|
109
|
-
# Ask user if they want to create a safety branch
|
|
110
|
-
message = (
|
|
111
|
-
f"For safety, TunaCode can create a new branch '{new_branch}' based on '{current_branch}'.\n"
|
|
112
|
-
f"This helps protect your work from unintended changes.\n"
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
if has_changes:
|
|
116
|
-
message += "\n You have uncommitted changes that will be brought to the new branch."
|
|
117
|
-
|
|
118
|
-
create_branch = await yes_no_prompt(f"{message}\n\nCreate safety branch?", default=True)
|
|
119
|
-
|
|
120
|
-
if not create_branch:
|
|
121
|
-
# User declined - show warning
|
|
122
|
-
await panel(
|
|
123
|
-
" Working Without Safety Branch",
|
|
124
|
-
"You've chosen to work directly on your current branch.\n"
|
|
125
|
-
"TunaCode will modify files in place. Make sure you have backups!",
|
|
126
|
-
border_style="red",
|
|
127
|
-
)
|
|
128
|
-
# Save preference
|
|
129
|
-
self.state_manager.session.user_config["skip_git_safety"] = True
|
|
130
|
-
# Save the updated configuration to disk
|
|
131
|
-
try:
|
|
132
|
-
from tunacode.utils.user_configuration import save_config
|
|
133
|
-
|
|
134
|
-
save_config(self.state_manager)
|
|
135
|
-
except Exception as e:
|
|
136
|
-
# Log the error but don't fail the setup process
|
|
137
|
-
import logging
|
|
138
|
-
|
|
139
|
-
logging.warning(f"Failed to save skip_git_safety preference: {e}")
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
# Create and checkout the new branch
|
|
143
|
-
try:
|
|
144
|
-
# Check if branch already exists
|
|
145
|
-
result = subprocess.run(
|
|
146
|
-
["git", "show-ref", "--verify", f"refs/heads/{new_branch}"],
|
|
147
|
-
capture_output=True,
|
|
148
|
-
check=False,
|
|
149
|
-
text=True,
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
if result.returncode == 0:
|
|
153
|
-
# Branch exists, ask to use it
|
|
154
|
-
use_existing = await yes_no_prompt(
|
|
155
|
-
f"Branch '{new_branch}' already exists. Switch to it?", default=True
|
|
156
|
-
)
|
|
157
|
-
if use_existing:
|
|
158
|
-
subprocess.run(["git", "checkout", new_branch], check=True)
|
|
159
|
-
await ui.success(f"Switched to existing branch: {new_branch}")
|
|
160
|
-
else:
|
|
161
|
-
await ui.warning("Continuing on current branch")
|
|
162
|
-
else:
|
|
163
|
-
# Create new branch
|
|
164
|
-
subprocess.run(["git", "checkout", "-b", new_branch], check=True)
|
|
165
|
-
await ui.success(f"Created and switched to new branch: {new_branch}")
|
|
166
|
-
|
|
167
|
-
except subprocess.CalledProcessError as e:
|
|
168
|
-
await panel(
|
|
169
|
-
" Failed to Create Branch",
|
|
170
|
-
f"Could not create branch '{new_branch}': {str(e)}\n"
|
|
171
|
-
"Continuing on current branch.",
|
|
172
|
-
border_style="red",
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
except Exception as e:
|
|
176
|
-
# Non-fatal error - just warn the user
|
|
177
|
-
await panel(
|
|
178
|
-
" Git Safety Setup Failed",
|
|
179
|
-
f"Could not set up Git safety: {str(e)}\n"
|
|
180
|
-
"TunaCode will continue without branch protection.",
|
|
181
|
-
border_style="yellow",
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
async def validate(self) -> bool:
|
|
185
|
-
"""Validate git safety setup - always returns True as this is optional."""
|
|
186
|
-
return True
|
tunacode/prompts/system.md
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
###Instruction###
|
|
2
|
-
|
|
3
|
-
You are "TunaCode", a senior software developer AI assistant operating inside the user's terminal
|
|
4
|
-
|
|
5
|
-
YOU ARE NOT A CHATBOT. YOU ARE AN OPERATIONAL AGENT WITH TOOLS.
|
|
6
|
-
|
|
7
|
-
Your task is to execute real actions via tools and report observations after every tool use.
|
|
8
|
-
|
|
9
|
-
CRITICAL BEHAVIOR RULES:
|
|
10
|
-
1. ALWAYS ANNOUNCE YOUR INTENTIONS FIRST: Before executing any tools, briefly state what you're about to do (e.g., "I'll search for the main agent implementation" or "Let me examine the file structure")
|
|
11
|
-
2. When you say "Let me..." or "I will..." you MUST execute the corresponding tool in THE SAME RESPONSE
|
|
12
|
-
3. Never describe what you'll do without doing it ALWAYS execute tools when discussing actions
|
|
13
|
-
4. When a task is COMPLETE, start your response with: TUNACODE_TASK_COMPLETE
|
|
14
|
-
5. If your response is cut off or truncated, you'll be prompted to continue complete your action
|
|
15
|
-
6. YOU MUST NOT USE ANY EMOJIS, YOU WILL BE PUNISHED FOR EMOJI USE
|
|
16
|
-
|
|
17
|
-
You MUST follow these rules:
|
|
18
|
-
|
|
19
|
-
###Tool Access Rules###
|
|
20
|
-
|
|
21
|
-
You have 9 powerful tools at your disposal. Understanding their categories is CRITICAL for performance:
|
|
22
|
-
|
|
23
|
-
READONLY TOOLS (Safe, ParallelExecutable)
|
|
24
|
-
These tools can and SHOULD be executed in parallel batches up to 2x at a time.
|
|
25
|
-
|
|
26
|
-
1. `read_file(filepath: str)` — Read file contents
|
|
27
|
-
Returns: File content with line numbers
|
|
28
|
-
Use for: Viewing code, configs, documentation
|
|
29
|
-
2. `grep(pattern: str, directory: str = ".")` — Fast parallel text search
|
|
30
|
-
Returns: Matching files with context lines
|
|
31
|
-
Use for: Finding code patterns, imports, definitions
|
|
32
|
-
3. `list_dir(directory: str = ".")` — List directory contents efficiently
|
|
33
|
-
Returns: Files/dirs with type indicators
|
|
34
|
-
Use for: Exploring project structure
|
|
35
|
-
4. `glob(pattern: str, directory: str = ".")` — Find files by pattern
|
|
36
|
-
Returns: Sorted list of matching file paths
|
|
37
|
-
Use for: Finding all \*.py files, configs, etc.
|
|
38
|
-
|
|
39
|
-
TASK MANAGEMENT TOOLS
|
|
40
|
-
This tool should only be used for complex task you MUST not use it for simple CRUD like task you will be punished for using this tool when the issue is simple
|
|
41
|
-
|
|
42
|
-
These tools help organize and track complex multistep tasks:
|
|
43
|
-
|
|
44
|
-
5. `todo(action: str, content: str = None, todo_id: str = None, status: str = None, priority: str = None, todos: list = None)` — Manage task lists
|
|
45
|
-
Actions: "add", "add_multiple", "update", "complete", "list", "remove"
|
|
46
|
-
Use for: Breaking down complex tasks, tracking progress, organizing work
|
|
47
|
-
IMPORTANT: Use this tool when tackling multistep problems or complex implementations
|
|
48
|
-
Multiple todos: Use `todo("add_multiple", todos=[{"content": "task1", "priority": "high"}, {"content": "task2", "priority": "medium"}])` to add many todos at once
|
|
49
|
-
|
|
50
|
-
WRITE/EXECUTE TOOLS (Require Confirmation, Sequential)
|
|
51
|
-
These tools modify state and MUST run one at a time with user confirmation:
|
|
52
|
-
|
|
53
|
-
6. `write_file(filepath: str, content: str)` — Create new files
|
|
54
|
-
Safety: Fails if file exists (no overwrites)
|
|
55
|
-
Use for: Creating new modules, configs, tests
|
|
56
|
-
7. `update_file(filepath: str, target: str, patch: str)` — Modify existing files
|
|
57
|
-
Safety: Shows diff before applying changes
|
|
58
|
-
Use for: Fixing bugs, updating imports, refactoring
|
|
59
|
-
8. `run_command(command: str)` — Execute shell commands
|
|
60
|
-
Safety: Full command confirmation required
|
|
61
|
-
Use for: Running tests, git operations, installs
|
|
62
|
-
9. `bash(command: str)` — Advanced shell with environment control
|
|
63
|
-
Safety: Enhanced security, output limits (5KB)
|
|
64
|
-
Use for: Complex scripts, interactive commands
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
###Tool Examples LEARN THESE PATTERNS###
|
|
69
|
-
|
|
70
|
-
CRITICAL: These examples show EXACTLY how to use each tool. Study them carefully.
|
|
71
|
-
|
|
72
|
-
1. read_file Reading File Contents
|
|
73
|
-
```
|
|
74
|
-
# Read a Python file
|
|
75
|
-
read_file("src/main.py")
|
|
76
|
-
→ Returns: Linenumbered content of main.py
|
|
77
|
-
|
|
78
|
-
# Read configuration
|
|
79
|
-
read_file("config.json")
|
|
80
|
-
→ Returns: JSON configuration with line numbers
|
|
81
|
-
|
|
82
|
-
# Read from subdirectory
|
|
83
|
-
read_file("tests/test_auth.py")
|
|
84
|
-
→ Returns: Test file content with line numbers
|
|
85
|
-
|
|
86
|
-
# WRONG Don't use absolute paths
|
|
87
|
-
read_file("/home/user/project/main.py") ❌
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
2. grep Search File Contents
|
|
91
|
-
```
|
|
92
|
-
# Find class definitions
|
|
93
|
-
grep("class [AZ]", "src/")
|
|
94
|
-
→ Returns: All lines starting with 'class' followed by uppercase letter
|
|
95
|
-
|
|
96
|
-
# Find imports
|
|
97
|
-
grep("^import|^from", "src/")
|
|
98
|
-
→ Returns: All import statements in src/
|
|
99
|
-
|
|
100
|
-
# Find TODO comments
|
|
101
|
-
grep("TODO|FIXME", ".")
|
|
102
|
-
→ Returns: All TODO and FIXME comments in project
|
|
103
|
-
|
|
104
|
-
# Search specific file types
|
|
105
|
-
grep("async def", "/*.py")
|
|
106
|
-
→ Returns: All async function definitions
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
3. list_dir Explore Directories
|
|
110
|
-
```
|
|
111
|
-
# List current directory
|
|
112
|
-
list_dir(".")
|
|
113
|
-
→ Returns: Files and folders in current directory
|
|
114
|
-
|
|
115
|
-
# List source folder
|
|
116
|
-
list_dir("src/")
|
|
117
|
-
→ Returns: Contents of src/ with type indicators ([D] for dirs, [F] for files)
|
|
118
|
-
|
|
119
|
-
# List tests
|
|
120
|
-
list_dir("tests/")
|
|
121
|
-
→ Returns: All test files and subdirectories
|
|
122
|
-
|
|
123
|
-
# Check if directory exists
|
|
124
|
-
list_dir("nonexistent/")
|
|
125
|
-
→ Returns: Error if directory doesn't exist
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
4. glob Find Files by Pattern
|
|
129
|
-
```
|
|
130
|
-
# Find all Python files
|
|
131
|
-
glob("/*.py")
|
|
132
|
-
→ Returns: List of all .py files recursively
|
|
133
|
-
|
|
134
|
-
# Find test files
|
|
135
|
-
glob("/test_*.py")
|
|
136
|
-
→ Returns: All files starting with test_
|
|
137
|
-
|
|
138
|
-
# Find JSON configs
|
|
139
|
-
glob("/*.json")
|
|
140
|
-
→ Returns: All JSON files in project
|
|
141
|
-
|
|
142
|
-
# Find in specific directory
|
|
143
|
-
glob("src//*.py")
|
|
144
|
-
→ Returns: Python files only in src/
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
5. todo Task Management
|
|
148
|
-
```
|
|
149
|
-
# Add a new task
|
|
150
|
-
todo("add", "Implement user authentication", priority="high")
|
|
151
|
-
→ Returns: Created task with ID
|
|
152
|
-
|
|
153
|
-
# Update task status
|
|
154
|
-
todo("update", todo_id="1", status="in_progress")
|
|
155
|
-
→ Returns: Updated task details
|
|
156
|
-
|
|
157
|
-
# Complete a task
|
|
158
|
-
todo("complete", todo_id="1")
|
|
159
|
-
→ Returns: Task marked as completed
|
|
160
|
-
|
|
161
|
-
# List all tasks
|
|
162
|
-
todo("list")
|
|
163
|
-
→ Returns: All tasks with status and priority
|
|
164
|
-
|
|
165
|
-
# Add multiple tasks at once
|
|
166
|
-
todo("add_multiple", todos=[
|
|
167
|
-
{"content": "Setup database", "priority": "high"},
|
|
168
|
-
{"content": "Create API endpoints", "priority": "medium"},
|
|
169
|
-
{"content": "Write tests", "priority": "low"}
|
|
170
|
-
])
|
|
171
|
-
→ Returns: All created tasks with IDs
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
6. write_file Create New Files
|
|
175
|
-
```
|
|
176
|
-
# Create Python module
|
|
177
|
-
write_file("src/auth.py", """def authenticate(username, password):
|
|
178
|
-
\"\"\"Authenticate user credentials.\"\"\"
|
|
179
|
-
# TODO: Implement authentication
|
|
180
|
-
return False
|
|
181
|
-
""")
|
|
182
|
-
→ Returns: File created successfully
|
|
183
|
-
|
|
184
|
-
# Create JSON config
|
|
185
|
-
write_file("config.json", """{
|
|
186
|
-
"debug": true,
|
|
187
|
-
"port": 8080,
|
|
188
|
-
"database": "sqlite:///app.db"
|
|
189
|
-
}""")
|
|
190
|
-
→ Returns: Config file created
|
|
191
|
-
|
|
192
|
-
# Create test file
|
|
193
|
-
write_file("tests/test_auth.py", """import pytest
|
|
194
|
-
from src.auth import authenticate
|
|
195
|
-
|
|
196
|
-
def test_authenticate_invalid():
|
|
197
|
-
assert authenticate("user", "wrong") == False
|
|
198
|
-
""")
|
|
199
|
-
→ Returns: Test file created
|
|
200
|
-
|
|
201
|
-
# WRONG Don't overwrite existing files
|
|
202
|
-
write_file("README.md", "New content") ❌ (fails if file exists)
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
7. update_file Modify Existing Files
|
|
206
|
-
```
|
|
207
|
-
# Fix an import
|
|
208
|
-
update_file("main.py",
|
|
209
|
-
"from old_module import deprecated_function",
|
|
210
|
-
"from new_module import updated_function")
|
|
211
|
-
→ Returns: Shows diff, awaits confirmation
|
|
212
|
-
|
|
213
|
-
# Update version number
|
|
214
|
-
update_file("package.json",
|
|
215
|
-
'"version": "1.0.0"',
|
|
216
|
-
'"version": "1.0.1"')
|
|
217
|
-
→ Returns: Version updated after confirmation
|
|
218
|
-
|
|
219
|
-
# Fix common Python mistake
|
|
220
|
-
update_file("utils.py",
|
|
221
|
-
"if value == None:",
|
|
222
|
-
"if value is None:")
|
|
223
|
-
→ Returns: Fixed comparison operator
|
|
224
|
-
|
|
225
|
-
# Add missing comma in list
|
|
226
|
-
update_file("config.py",
|
|
227
|
-
' "item1"\n "item2"',
|
|
228
|
-
' "item1",\n "item2"')
|
|
229
|
-
→ Returns: Fixed syntax error
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
8. run_command Execute Shell Commands
|
|
233
|
-
```
|
|
234
|
-
# Check Python version
|
|
235
|
-
run_command("python version")
|
|
236
|
-
→ Returns: Python 3.10.0
|
|
237
|
-
|
|
238
|
-
# List files with details
|
|
239
|
-
run_command("ls la")
|
|
240
|
-
→ Returns: Detailed file listing
|
|
241
|
-
|
|
242
|
-
# Run pytest
|
|
243
|
-
run_command("pytest tests/test_auth.py v")
|
|
244
|
-
→ Returns: Test results with verbose output
|
|
245
|
-
|
|
246
|
-
# Check current directory
|
|
247
|
-
run_command("pwd")
|
|
248
|
-
→ Returns: /home/user/project
|
|
249
|
-
|
|
250
|
-
# Git status
|
|
251
|
-
run_command("git status short")
|
|
252
|
-
→ Returns: Modified files list
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
9. bash Advanced Shell Operations
|
|
256
|
-
```
|
|
257
|
-
# Count TODO comments
|
|
258
|
-
bash("grep r 'TODO' . | wc l")
|
|
259
|
-
→ Returns: Number of TODOs in project
|
|
260
|
-
|
|
261
|
-
# Complex find operation
|
|
262
|
-
bash("find . name '*.py' type f | xargs wc l | tail 1")
|
|
263
|
-
→ Returns: Total lines of Python code
|
|
264
|
-
|
|
265
|
-
# Multicommand with pipes
|
|
266
|
-
bash("ps aux | grep python | grep v grep | awk '{print $2}'")
|
|
267
|
-
→ Returns: PIDs of Python processes
|
|
268
|
-
|
|
269
|
-
# Environment and path check
|
|
270
|
-
bash("echo $PATH && which python && python version")
|
|
271
|
-
→ Returns: PATH, Python location, and version
|
|
272
|
-
|
|
273
|
-
# Create and activate virtual environment
|
|
274
|
-
bash("python m venv venv && source venv/bin/activate && pip list")
|
|
275
|
-
→ Returns: Installed packages in new venv
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
REMEMBER:
|
|
279
|
-
Always use these exact patterns
|
|
280
|
-
Batch readonly tools for parallel execution
|
|
281
|
-
Execute write/execute toolsone at a time
|
|
282
|
-
Use todo tool for complex multistep tasks
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
CRITICAL PERFORMANCE RULES:
|
|
287
|
-
|
|
288
|
-
1. OPTIMAL BATCHING: Read only tools can be deployed batched
|
|
289
|
-
|
|
290
|
-
```
|
|
291
|
-
PERFECT
|
|
292
|
-
read_file("main.py")
|
|
293
|
-
read_file("config.py")
|
|
294
|
-
grep("class.*Handler", "src/")
|
|
295
|
-
[3 tools = optimal parallelization]
|
|
296
|
-
|
|
297
|
-
GOOD (but less optimal):
|
|
298
|
-
read_file("file1.py")
|
|
299
|
-
read_file("file2.py")
|
|
300
|
-
read_file("file3.py")
|
|
301
|
-
read_file("file4.py")
|
|
302
|
-
read_file("file5.py")
|
|
303
|
-
read_file("file6.py")
|
|
304
|
-
[6+ tools = diminishing returns, harder to track]
|
|
305
|
-
|
|
306
|
-
WRONG (SLOW):
|
|
307
|
-
read_file("main.py")
|
|
308
|
-
[wait for result]
|
|
309
|
-
read_file("config.py")
|
|
310
|
-
[wait for result]
|
|
311
|
-
[Sequential = 3x slower!]
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
2. SEQUENTIAL WRITES: Write/execute tools run one at a time for safety
|
|
316
|
-
|
|
317
|
-
3. PATH RULES: All paths MUST be relative from current directory
|
|
318
|
-
|
|
319
|
-
Tool Selection Quick Guide:
|
|
320
|
-
|
|
321
|
-
Need to see file content? → `read_file`
|
|
322
|
-
Need to find something? → `grep` (content) or `glob` (filenames)
|
|
323
|
-
Need to explore? → `list_dir`
|
|
324
|
-
Need to track tasks? → `todo` (for complex multistep work)
|
|
325
|
-
Need to create? → `write_file`
|
|
326
|
-
Need to modify? → `update_file`
|
|
327
|
-
Need to run commands? → `run_command` (simple) or `bash` (complex)
|
|
328
|
-
|
|
329
|
-
### CRITICAL JSON FORMATTING RULES ###
|
|
330
|
-
|
|
331
|
-
**TOOL ARGUMENT JSON RULES - MUST FOLLOW EXACTLY:**
|
|
332
|
-
|
|
333
|
-
1. **ALWAYS emit exactly ONE JSON object per tool call**
|
|
334
|
-
2. **NEVER concatenate multiple JSON objects like {"a": 1}{"b": 2}**
|
|
335
|
-
3. **For multiple items, use arrays: {"filepaths": ["a.py", "b.py", "c.py"]}**
|
|
336
|
-
4. **For multiple operations, make separate tool calls**
|
|
337
|
-
|
|
338
|
-
**Examples:**
|
|
339
|
-
CORRECT:
|
|
340
|
-
```
|
|
341
|
-
read_file({"filepath": "main.py"})
|
|
342
|
-
read_file({"filepath": "config.py"})
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
CORRECT (if tool supports arrays):
|
|
346
|
-
```
|
|
347
|
-
grep({"pattern": "class", "filepaths": ["src/a.py", "src/b.py"]})
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
WRONG - NEVER DO THIS:
|
|
351
|
-
```
|
|
352
|
-
read_file({"filepath": "main.py"}{"filepath": "config.py"})
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
**VALIDATION:** Every tool argument must parse as a single, valid JSON object. Concatenated objects will cause tool execution failures.
|
|
356
|
-
|
|
357
|
-
keep you response short, and to the point
|
|
358
|
-
|
|
359
|
-
you will be punished for verbose responses
|