tunacode-cli 0.0.33__py3-none-any.whl → 0.0.34__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.py +38 -4
- tunacode/constants.py +1 -1
- tunacode/core/agents/main.py +28 -0
- tunacode/core/setup/config_setup.py +15 -9
- tunacode/utils/user_configuration.py +20 -3
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/METADATA +20 -1
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/RECORD +11 -11
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/WHEEL +0 -0
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/entry_points.txt +0 -0
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/licenses/LICENSE +0 -0
- {tunacode_cli-0.0.33.dist-info → tunacode_cli-0.0.34.dist-info}/top_level.txt +0 -0
tunacode/cli/commands.py
CHANGED
|
@@ -6,7 +6,7 @@ from enum import Enum
|
|
|
6
6
|
from typing import Any, Dict, List, Optional, Type
|
|
7
7
|
|
|
8
8
|
from .. import utils
|
|
9
|
-
from ..exceptions import ValidationError
|
|
9
|
+
from ..exceptions import ConfigurationError, ValidationError
|
|
10
10
|
from ..types import CommandArgs, CommandContext, CommandResult, ProcessRequestCallback
|
|
11
11
|
from ..ui import console as ui
|
|
12
12
|
|
|
@@ -628,9 +628,13 @@ class ModelCommand(SimpleCommand):
|
|
|
628
628
|
|
|
629
629
|
# Check if setting as default
|
|
630
630
|
if len(args) > 1 and args[1] == "default":
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
631
|
+
try:
|
|
632
|
+
utils.user_configuration.set_default_model(model_name, context.state_manager)
|
|
633
|
+
await ui.muted("Updating default model")
|
|
634
|
+
return "restart"
|
|
635
|
+
except ConfigurationError as e:
|
|
636
|
+
await ui.error(str(e))
|
|
637
|
+
return None
|
|
634
638
|
|
|
635
639
|
# Show success message with the new model
|
|
636
640
|
await ui.success(f"Switched to model: {model_name}")
|
|
@@ -669,6 +673,35 @@ class CommandFactory:
|
|
|
669
673
|
setattr(self.dependencies, key, value)
|
|
670
674
|
|
|
671
675
|
|
|
676
|
+
class InitCommand(SimpleCommand):
|
|
677
|
+
"""Creates or updates TUNACODE.md with project-specific context."""
|
|
678
|
+
|
|
679
|
+
spec = CommandSpec(
|
|
680
|
+
name="/init",
|
|
681
|
+
aliases=[],
|
|
682
|
+
description="Analyze codebase and create/update TUNACODE.md file",
|
|
683
|
+
category=CommandCategory.DEVELOPMENT,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
async def execute(self, args, context: CommandContext) -> CommandResult:
|
|
687
|
+
"""Execute the init command."""
|
|
688
|
+
# Minimal implementation to make test pass
|
|
689
|
+
prompt = """Please analyze this codebase and create a TUNACODE.md file containing:
|
|
690
|
+
1. Build/lint/test commands - especially for running a single test
|
|
691
|
+
2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
|
|
692
|
+
|
|
693
|
+
The file you create will be given to agentic coding agents (such as yourself) that operate in this repository.
|
|
694
|
+
Make it about 20 lines long.
|
|
695
|
+
If there's already a TUNACODE.md, improve it.
|
|
696
|
+
If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md),
|
|
697
|
+
make sure to include them."""
|
|
698
|
+
|
|
699
|
+
# Call the agent to analyze and create/update the file
|
|
700
|
+
await context.process_request(prompt, context.state_manager)
|
|
701
|
+
|
|
702
|
+
return None
|
|
703
|
+
|
|
704
|
+
|
|
672
705
|
class CommandRegistry:
|
|
673
706
|
"""Registry for managing commands with auto-discovery and categories."""
|
|
674
707
|
|
|
@@ -726,6 +759,7 @@ class CommandRegistry:
|
|
|
726
759
|
BranchCommand,
|
|
727
760
|
CompactCommand,
|
|
728
761
|
ModelCommand,
|
|
762
|
+
InitCommand,
|
|
729
763
|
]
|
|
730
764
|
|
|
731
765
|
# Register all discovered commands
|
tunacode/constants.py
CHANGED
tunacode/core/agents/main.py
CHANGED
|
@@ -457,6 +457,26 @@ def get_or_create_agent(model: ModelName, state_manager: StateManager) -> Pydant
|
|
|
457
457
|
# Use a default system prompt if neither file exists
|
|
458
458
|
system_prompt = "You are a helpful AI assistant for software development tasks."
|
|
459
459
|
|
|
460
|
+
# Load TUNACODE.md context
|
|
461
|
+
# Use sync version of get_code_style to avoid nested event loop issues
|
|
462
|
+
try:
|
|
463
|
+
from pathlib import Path as PathlibPath
|
|
464
|
+
|
|
465
|
+
tunacode_path = PathlibPath.cwd() / "TUNACODE.md"
|
|
466
|
+
if tunacode_path.exists():
|
|
467
|
+
tunacode_content = tunacode_path.read_text(encoding="utf-8")
|
|
468
|
+
if tunacode_content.strip():
|
|
469
|
+
# Log that we found TUNACODE.md
|
|
470
|
+
print("📄 TUNACODE.md located: Loading context...")
|
|
471
|
+
|
|
472
|
+
system_prompt += "\n\n# Project Context from TUNACODE.md\n" + tunacode_content
|
|
473
|
+
else:
|
|
474
|
+
# Log that TUNACODE.md was not found
|
|
475
|
+
print("📄 TUNACODE.md not found: Using default context")
|
|
476
|
+
except Exception:
|
|
477
|
+
# Ignore errors loading TUNACODE.md
|
|
478
|
+
pass
|
|
479
|
+
|
|
460
480
|
state_manager.session.agents[model] = Agent(
|
|
461
481
|
model=model,
|
|
462
482
|
system_prompt=system_prompt,
|
|
@@ -670,6 +690,14 @@ async def process_request(
|
|
|
670
690
|
# Create a request-level buffer for batching read-only tools across nodes
|
|
671
691
|
tool_buffer = ToolBuffer()
|
|
672
692
|
|
|
693
|
+
# Show TUNACODE.md preview if it was loaded and thoughts are enabled
|
|
694
|
+
if state_manager.session.show_thoughts and hasattr(state_manager, "tunacode_preview"):
|
|
695
|
+
from tunacode.ui import console as ui
|
|
696
|
+
|
|
697
|
+
await ui.muted(state_manager.tunacode_preview)
|
|
698
|
+
# Clear the preview after displaying it once
|
|
699
|
+
delattr(state_manager, "tunacode_preview")
|
|
700
|
+
|
|
673
701
|
# Show what we're sending to the API when thoughts are enabled
|
|
674
702
|
if state_manager.session.show_thoughts:
|
|
675
703
|
from tunacode.ui import console as ui
|
|
@@ -82,9 +82,13 @@ class ConfigSetup(BaseSetup):
|
|
|
82
82
|
):
|
|
83
83
|
self.state_manager.session.user_config = {}
|
|
84
84
|
self.state_manager.session.user_config = DEFAULT_USER_CONFIG.copy()
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
try:
|
|
86
|
+
user_configuration.save_config(
|
|
87
|
+
self.state_manager
|
|
88
|
+
) # Save the default config initially
|
|
89
|
+
except ConfigurationError as e:
|
|
90
|
+
await ui.error(str(e))
|
|
91
|
+
raise
|
|
88
92
|
await self._onboarding()
|
|
89
93
|
else:
|
|
90
94
|
# No config found - show CLI usage instead of onboarding
|
|
@@ -172,11 +176,12 @@ class ConfigSetup(BaseSetup):
|
|
|
172
176
|
# Compare configs to see if anything changed
|
|
173
177
|
current_config = json.dumps(self.state_manager.session.user_config, sort_keys=True)
|
|
174
178
|
if initial_config != current_config:
|
|
175
|
-
|
|
179
|
+
try:
|
|
180
|
+
user_configuration.save_config(self.state_manager)
|
|
176
181
|
message = f"Config saved to: [bold]{self.config_file}[/bold]"
|
|
177
182
|
await ui.panel("Finished", message, top=0, border_style=UI_COLORS["success"])
|
|
178
|
-
|
|
179
|
-
await ui.error(
|
|
183
|
+
except ConfigurationError as e:
|
|
184
|
+
await ui.error(str(e))
|
|
180
185
|
else:
|
|
181
186
|
await ui.panel(
|
|
182
187
|
"Setup canceled",
|
|
@@ -320,8 +325,9 @@ class ConfigSetup(BaseSetup):
|
|
|
320
325
|
]
|
|
321
326
|
|
|
322
327
|
# Save the configuration
|
|
323
|
-
|
|
328
|
+
try:
|
|
329
|
+
user_configuration.save_config(self.state_manager)
|
|
324
330
|
await ui.warning("Model set without validation - verify the model name is correct")
|
|
325
331
|
await ui.success(f"Configuration saved to: {self.config_file}")
|
|
326
|
-
|
|
327
|
-
await ui.error(
|
|
332
|
+
except ConfigurationError as e:
|
|
333
|
+
await ui.error(str(e))
|
|
@@ -58,11 +58,23 @@ def save_config(state_manager: "StateManager") -> bool:
|
|
|
58
58
|
"""Save user config to file"""
|
|
59
59
|
app_settings = ApplicationSettings()
|
|
60
60
|
try:
|
|
61
|
+
# Ensure config directory exists
|
|
62
|
+
app_settings.paths.config_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
# Write config file
|
|
61
65
|
with open(app_settings.paths.config_file, "w") as f:
|
|
62
66
|
json.dump(state_manager.session.user_config, f, indent=4)
|
|
63
67
|
return True
|
|
64
|
-
except
|
|
65
|
-
|
|
68
|
+
except PermissionError as e:
|
|
69
|
+
raise ConfigurationError(
|
|
70
|
+
f"Permission denied writing to {app_settings.paths.config_file}: {e}"
|
|
71
|
+
)
|
|
72
|
+
except OSError as e:
|
|
73
|
+
raise ConfigurationError(
|
|
74
|
+
f"Failed to save configuration to {app_settings.paths.config_file}: {e}"
|
|
75
|
+
)
|
|
76
|
+
except Exception as e:
|
|
77
|
+
raise ConfigurationError(f"Unexpected error saving configuration: {e}")
|
|
66
78
|
|
|
67
79
|
|
|
68
80
|
def get_mcp_servers(state_manager: "StateManager") -> MCPServers:
|
|
@@ -73,4 +85,9 @@ def get_mcp_servers(state_manager: "StateManager") -> MCPServers:
|
|
|
73
85
|
def set_default_model(model_name: ModelName, state_manager: "StateManager") -> bool:
|
|
74
86
|
"""Set the default model in the user config and save"""
|
|
75
87
|
state_manager.session.user_config["default_model"] = model_name
|
|
76
|
-
|
|
88
|
+
try:
|
|
89
|
+
save_config(state_manager)
|
|
90
|
+
return True
|
|
91
|
+
except ConfigurationError:
|
|
92
|
+
# Re-raise ConfigurationError to be handled by caller
|
|
93
|
+
raise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tunacode-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.34
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Author-email: larock22 <noreply@github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -40,6 +40,7 @@ Dynamic: license-file
|
|
|
40
40
|
<div align="center">
|
|
41
41
|
|
|
42
42
|
[](https://badge.fury.io/py/tunacode-cli)
|
|
43
|
+
[](https://pepy.tech/project/tunacode-cli)
|
|
43
44
|
[](https://www.python.org/downloads/)
|
|
44
45
|
[](https://opensource.org/licenses/MIT)
|
|
45
46
|
|
|
@@ -78,6 +79,17 @@ tunacode --model "openrouter:openai/gpt-4o" --key "sk-or-your-openrouter-key"
|
|
|
78
79
|
|
|
79
80
|
Your config is saved to `~/.config/tunacode.json` (edit directly with `nvim ~/.config/tunacode.json`)
|
|
80
81
|
|
|
82
|
+
### Recommended Models
|
|
83
|
+
|
|
84
|
+
Based on extensive testing, these models provide the best performance:
|
|
85
|
+
- `google/gemini-2.5-pro` - Excellent for complex reasoning
|
|
86
|
+
- `openai/gpt-4.1` - Strong general-purpose model
|
|
87
|
+
- `deepseek/deepseek-r1-0528` - Great for code generation
|
|
88
|
+
- `openai/gpt-4.1-mini` - Fast and cost-effective
|
|
89
|
+
- `anthropic/claude-4-sonnet-20250522` - Superior context handling
|
|
90
|
+
|
|
91
|
+
*Note: Formal evaluations coming soon. Any model can work, but these have shown the best results in practice.*
|
|
92
|
+
|
|
81
93
|
## Start Coding
|
|
82
94
|
|
|
83
95
|
```bash
|
|
@@ -105,6 +117,13 @@ TunaCode leverages parallel execution for read-only operations, achieving **3x f
|
|
|
105
117
|
|
|
106
118
|
Multiple file reads, directory listings, and searches execute concurrently using async I/O, making code exploration significantly faster.
|
|
107
119
|
|
|
120
|
+
## Features in Development
|
|
121
|
+
|
|
122
|
+
- **Streaming UI**: Currently working on implementing streaming responses for better user experience
|
|
123
|
+
- **Bug Fixes**: Actively addressing issues - please report any bugs you encounter!
|
|
124
|
+
|
|
125
|
+
*Note: While the tool is fully functional, we're focusing on stability and core features before optimizing for speed.*
|
|
126
|
+
|
|
108
127
|
## Safety First
|
|
109
128
|
|
|
110
129
|
⚠️ **Important**: TunaCode can modify your codebase. Always:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
tunacode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
tunacode/constants.py,sha256=
|
|
2
|
+
tunacode/constants.py,sha256=SIhhV5x1ESvfVaAki0nJ9XVlKZOwwomqIMT73FLyjPY,4074
|
|
3
3
|
tunacode/context.py,sha256=6sterdRvPOyG3LU0nEAXpBsEPZbO3qtPyTlJBi-_VXE,2612
|
|
4
4
|
tunacode/exceptions.py,sha256=mTWXuWyr1k16CGLWN2tsthDGi7lbx1JK0ekIqogYDP8,3105
|
|
5
5
|
tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
tunacode/setup.py,sha256=dYn0NeAxtNIDSogWEmGSyjb9wsr8AonZ8vAo5sw9NIw,1909
|
|
7
7
|
tunacode/types.py,sha256=BciT-uxnQ44iC-4QiDY72OD23LOtqSyMOuK_N0ttlaA,7676
|
|
8
8
|
tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
|
|
9
|
-
tunacode/cli/commands.py,sha256=
|
|
9
|
+
tunacode/cli/commands.py,sha256=DEEfDVNzDmMRUhA7JfWGh8antnMeb3G6LmaJLqNVsoI,31293
|
|
10
10
|
tunacode/cli/main.py,sha256=PIcFnfmIoI_pmK2y-zB_ouJbzR5fbSI7zsKQNPB_J8o,2406
|
|
11
11
|
tunacode/cli/repl.py,sha256=o3bn9BYQsy3TFCWJq-fzeHKLrM2KInSrMF5E5_RqSOY,13736
|
|
12
12
|
tunacode/cli/textual_app.py,sha256=14-Nt0IIETmyHBrNn9uwSF3EwCcutwTp6gdoKgNm0sY,12593
|
|
@@ -20,14 +20,14 @@ tunacode/core/code_index.py,sha256=jgAx3lSWP_DwnyiP5Jkm1YvX4JJyI4teMzlNrJSpEOA,1
|
|
|
20
20
|
tunacode/core/state.py,sha256=PHGCGjx_X03I5jO-T1JkREQm4cwYEXQty59JJlnk24c,1608
|
|
21
21
|
tunacode/core/tool_handler.py,sha256=BPjR013OOO0cLXPdLeL2FDK0ixUwOYu59FfHdcdFhp4,2277
|
|
22
22
|
tunacode/core/agents/__init__.py,sha256=UUJiPYb91arwziSpjd7vIk7XNGA_4HQbsOIbskSqevA,149
|
|
23
|
-
tunacode/core/agents/main.py,sha256
|
|
23
|
+
tunacode/core/agents/main.py,sha256=-QwKSKoPLdD-JlKPjwMUSxNu_TSrj-pdUleWR2FN-A0,39441
|
|
24
24
|
tunacode/core/background/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
tunacode/core/background/manager.py,sha256=rJdl3eDLTQwjbT7VhxXcJbZopCNR3M8ZGMbmeVnwwMc,1126
|
|
26
26
|
tunacode/core/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
tunacode/core/setup/__init__.py,sha256=lzdpY6rIGf9DDlDBDGFvQZaSOQeFsNglHbkpq1-GtU8,376
|
|
28
28
|
tunacode/core/setup/agent_setup.py,sha256=trELO8cPnWo36BBnYmXDEnDPdhBg0p-VLnx9A8hSSSQ,1401
|
|
29
29
|
tunacode/core/setup/base.py,sha256=cbyT2-xK2mWgH4EO17VfM_OM2bj0kT895NW2jSXbe3c,968
|
|
30
|
-
tunacode/core/setup/config_setup.py,sha256=
|
|
30
|
+
tunacode/core/setup/config_setup.py,sha256=LnIGZrqDCWUhiMhJMnKX1gyaZhy6pKM8xf_fy_t9B3U,14516
|
|
31
31
|
tunacode/core/setup/coordinator.py,sha256=oVTN2xIeJERXitVJpkIk9tDGLs1D1bxIRmaogJwZJFI,2049
|
|
32
32
|
tunacode/core/setup/environment_setup.py,sha256=n3IrObKEynHZSwtUJ1FddMg2C4sHz7ca42awemImV8s,2225
|
|
33
33
|
tunacode/core/setup/git_safety_setup.py,sha256=CRIqrQt0QUJQRS344njty_iCqTorrDhHlXRuET7w0Tk,6714
|
|
@@ -67,10 +67,10 @@ tunacode/utils/ripgrep.py,sha256=AXUs2FFt0A7KBV996deS8wreIlUzKOlAHJmwrcAr4No,583
|
|
|
67
67
|
tunacode/utils/system.py,sha256=FSoibTIH0eybs4oNzbYyufIiV6gb77QaeY2yGqW39AY,11381
|
|
68
68
|
tunacode/utils/text_utils.py,sha256=zRBaorvtyd7HBEWtIfCH1Wce1L6rhsQwpORUEGBFMjA,2981
|
|
69
69
|
tunacode/utils/token_counter.py,sha256=nGCWwrHHFbKywqeDCEuJnADCkfJuzysWiB6cCltJOKI,648
|
|
70
|
-
tunacode/utils/user_configuration.py,sha256=
|
|
71
|
-
tunacode_cli-0.0.
|
|
72
|
-
tunacode_cli-0.0.
|
|
73
|
-
tunacode_cli-0.0.
|
|
74
|
-
tunacode_cli-0.0.
|
|
75
|
-
tunacode_cli-0.0.
|
|
76
|
-
tunacode_cli-0.0.
|
|
70
|
+
tunacode/utils/user_configuration.py,sha256=Ilz8dpGVJDBE2iLWHAPT0xR8D51VRKV3kIbsAz8Bboc,3275
|
|
71
|
+
tunacode_cli-0.0.34.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
72
|
+
tunacode_cli-0.0.34.dist-info/METADATA,sha256=uZKr-BnaxT_7vB1gTSIMEnWx1tfOSbBtPAt7gY4pibY,4943
|
|
73
|
+
tunacode_cli-0.0.34.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
74
|
+
tunacode_cli-0.0.34.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
|
|
75
|
+
tunacode_cli-0.0.34.dist-info/top_level.txt,sha256=lKy2P6BWNi5XSA4DHFvyjQ14V26lDZctwdmhEJrxQbU,9
|
|
76
|
+
tunacode_cli-0.0.34.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|