tunacode-cli 0.0.76.9__py3-none-any.whl → 0.0.77.2__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/implementations/development.py +4 -4
- tunacode/configuration/key_descriptions.py +2 -9
- tunacode/constants.py +2 -2
- tunacode/context.py +5 -5
- tunacode/core/agents/agent_components/__init__.py +2 -0
- tunacode/core/agents/agent_components/agent_config.py +41 -38
- tunacode/core/agents/agent_components/agent_helpers.py +27 -0
- tunacode/core/agents/main.py +6 -65
- tunacode/core/setup/__init__.py +0 -2
- tunacode/prompts/{system.md → system.xml} +10 -7
- tunacode/setup.py +0 -2
- tunacode/tools/grep.py +3 -16
- tunacode/ui/console.py +61 -11
- tunacode/ui/output.py +35 -19
- tunacode/ui/panels.py +69 -32
- tunacode/utils/models_registry.py +3 -3
- {tunacode_cli-0.0.76.9.dist-info → tunacode_cli-0.0.77.2.dist-info}/METADATA +2 -2
- {tunacode_cli-0.0.76.9.dist-info → tunacode_cli-0.0.77.2.dist-info}/RECORD +21 -22
- tunacode/core/setup/git_safety_setup.py +0 -186
- {tunacode_cli-0.0.76.9.dist-info → tunacode_cli-0.0.77.2.dist-info}/WHEEL +0 -0
- {tunacode_cli-0.0.76.9.dist-info → tunacode_cli-0.0.77.2.dist-info}/entry_points.txt +0 -0
- {tunacode_cli-0.0.76.9.dist-info → tunacode_cli-0.0.77.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|