tunacode-cli 0.0.47__py3-none-any.whl → 0.0.48__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/main.py +0 -4
- tunacode/cli/repl.py +7 -14
- tunacode/configuration/defaults.py +1 -0
- tunacode/constants.py +1 -6
- tunacode/core/agents/dspy_integration.py +223 -0
- tunacode/core/agents/dspy_tunacode.py +458 -0
- tunacode/core/agents/main.py +237 -311
- tunacode/core/agents/utils.py +6 -54
- tunacode/core/state.py +0 -41
- tunacode/exceptions.py +0 -23
- tunacode/prompts/dspy_task_planning.md +45 -0
- tunacode/prompts/dspy_tool_selection.md +58 -0
- tunacode/ui/input.py +1 -2
- tunacode/ui/keybindings.py +1 -17
- tunacode/ui/panels.py +2 -9
- tunacode/utils/token_counter.py +2 -1
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/METADATA +3 -3
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/RECORD +22 -26
- tunacode/core/recursive/__init__.py +0 -18
- tunacode/core/recursive/aggregator.py +0 -467
- tunacode/core/recursive/budget.py +0 -414
- tunacode/core/recursive/decomposer.py +0 -398
- tunacode/core/recursive/executor.py +0 -470
- tunacode/core/recursive/hierarchy.py +0 -487
- tunacode/ui/recursive_progress.py +0 -380
- tunacode/utils/retry.py +0 -163
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/WHEEL +0 -0
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/entry_points.txt +0 -0
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/licenses/LICENSE +0 -0
- {tunacode_cli-0.0.47.dist-info → tunacode_cli-0.0.48.dist-info}/top_level.txt +0 -0
tunacode/core/agents/utils.py
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import importlib
|
|
3
3
|
import json
|
|
4
|
-
import logging
|
|
5
4
|
import os
|
|
6
5
|
import re
|
|
7
6
|
from collections.abc import Iterator
|
|
8
7
|
from datetime import datetime, timezone
|
|
9
8
|
from typing import Any
|
|
10
9
|
|
|
11
|
-
from tunacode.constants import
|
|
12
|
-
JSON_PARSE_BASE_DELAY,
|
|
13
|
-
JSON_PARSE_MAX_DELAY,
|
|
14
|
-
JSON_PARSE_MAX_RETRIES,
|
|
15
|
-
READ_ONLY_TOOLS,
|
|
16
|
-
)
|
|
17
|
-
from tunacode.exceptions import ToolBatchingJSONError
|
|
10
|
+
from tunacode.constants import READ_ONLY_TOOLS
|
|
18
11
|
from tunacode.types import (
|
|
19
12
|
ErrorMessage,
|
|
20
13
|
StateManager,
|
|
@@ -23,9 +16,6 @@ from tunacode.types import (
|
|
|
23
16
|
ToolName,
|
|
24
17
|
)
|
|
25
18
|
from tunacode.ui import console as ui
|
|
26
|
-
from tunacode.utils.retry import retry_json_parse_async
|
|
27
|
-
|
|
28
|
-
logger = logging.getLogger(__name__)
|
|
29
19
|
|
|
30
20
|
|
|
31
21
|
# Lazy import for Agent and Tool
|
|
@@ -177,28 +167,11 @@ async def parse_json_tool_calls(
|
|
|
177
167
|
if brace_count == 0 and start_pos != -1:
|
|
178
168
|
potential_json = text[start_pos : i + 1]
|
|
179
169
|
try:
|
|
180
|
-
|
|
181
|
-
parsed = await retry_json_parse_async(
|
|
182
|
-
potential_json,
|
|
183
|
-
max_retries=JSON_PARSE_MAX_RETRIES,
|
|
184
|
-
base_delay=JSON_PARSE_BASE_DELAY,
|
|
185
|
-
max_delay=JSON_PARSE_MAX_DELAY,
|
|
186
|
-
)
|
|
170
|
+
parsed = json.loads(potential_json)
|
|
187
171
|
if isinstance(parsed, dict) and "tool" in parsed and "args" in parsed:
|
|
188
172
|
potential_jsons.append((parsed["tool"], parsed["args"]))
|
|
189
|
-
except json.JSONDecodeError
|
|
190
|
-
|
|
191
|
-
logger.error(f"JSON parsing failed after {JSON_PARSE_MAX_RETRIES} retries: {e}")
|
|
192
|
-
if state_manager.session.show_thoughts:
|
|
193
|
-
await ui.error(
|
|
194
|
-
f"Failed to parse tool JSON after {JSON_PARSE_MAX_RETRIES} retries"
|
|
195
|
-
)
|
|
196
|
-
# Raise custom exception for better error handling
|
|
197
|
-
raise ToolBatchingJSONError(
|
|
198
|
-
json_content=potential_json,
|
|
199
|
-
retry_count=JSON_PARSE_MAX_RETRIES,
|
|
200
|
-
original_error=e,
|
|
201
|
-
) from e
|
|
173
|
+
except json.JSONDecodeError:
|
|
174
|
+
pass
|
|
202
175
|
start_pos = -1
|
|
203
176
|
|
|
204
177
|
matches = potential_jsons
|
|
@@ -247,13 +220,7 @@ async def extract_and_execute_tool_calls(
|
|
|
247
220
|
|
|
248
221
|
for match in code_matches:
|
|
249
222
|
try:
|
|
250
|
-
|
|
251
|
-
tool_data = await retry_json_parse_async(
|
|
252
|
-
match,
|
|
253
|
-
max_retries=JSON_PARSE_MAX_RETRIES,
|
|
254
|
-
base_delay=JSON_PARSE_BASE_DELAY,
|
|
255
|
-
max_delay=JSON_PARSE_MAX_DELAY,
|
|
256
|
-
)
|
|
223
|
+
tool_data = json.loads(match)
|
|
257
224
|
if "tool" in tool_data and "args" in tool_data:
|
|
258
225
|
|
|
259
226
|
class MockToolCall:
|
|
@@ -273,22 +240,7 @@ async def extract_and_execute_tool_calls(
|
|
|
273
240
|
if state_manager.session.show_thoughts:
|
|
274
241
|
await ui.muted(f"FALLBACK: Executed {tool_data['tool']} from code block")
|
|
275
242
|
|
|
276
|
-
except json.JSONDecodeError as e:
|
|
277
|
-
# After all retries failed
|
|
278
|
-
logger.error(
|
|
279
|
-
f"Code block JSON parsing failed after {JSON_PARSE_MAX_RETRIES} retries: {e}"
|
|
280
|
-
)
|
|
281
|
-
if state_manager.session.show_thoughts:
|
|
282
|
-
await ui.error(
|
|
283
|
-
f"Failed to parse code block tool JSON after {JSON_PARSE_MAX_RETRIES} retries"
|
|
284
|
-
)
|
|
285
|
-
# Raise custom exception for better error handling
|
|
286
|
-
raise ToolBatchingJSONError(
|
|
287
|
-
json_content=match,
|
|
288
|
-
retry_count=JSON_PARSE_MAX_RETRIES,
|
|
289
|
-
original_error=e,
|
|
290
|
-
) from e
|
|
291
|
-
except (KeyError, Exception) as e:
|
|
243
|
+
except (json.JSONDecodeError, KeyError, Exception) as e:
|
|
292
244
|
if state_manager.session.show_thoughts:
|
|
293
245
|
await ui.error(f"Error parsing code block tool call: {e!s}")
|
|
294
246
|
|
tunacode/core/state.py
CHANGED
|
@@ -68,13 +68,6 @@ class SessionState:
|
|
|
68
68
|
"cost": 0.0,
|
|
69
69
|
}
|
|
70
70
|
)
|
|
71
|
-
# Recursive execution tracking
|
|
72
|
-
current_recursion_depth: int = 0
|
|
73
|
-
max_recursion_depth: int = 5
|
|
74
|
-
parent_task_id: Optional[str] = None
|
|
75
|
-
task_hierarchy: dict[str, Any] = field(default_factory=dict)
|
|
76
|
-
iteration_budgets: dict[str, int] = field(default_factory=dict)
|
|
77
|
-
recursive_context_stack: list[dict[str, Any]] = field(default_factory=list)
|
|
78
71
|
|
|
79
72
|
def update_token_count(self):
|
|
80
73
|
"""Calculates the total token count from messages and files in context."""
|
|
@@ -105,40 +98,6 @@ class StateManager:
|
|
|
105
98
|
todo.completed_at = datetime.now()
|
|
106
99
|
break
|
|
107
100
|
|
|
108
|
-
def push_recursive_context(self, context: dict[str, Any]) -> None:
|
|
109
|
-
"""Push a new context onto the recursive execution stack."""
|
|
110
|
-
self._session.recursive_context_stack.append(context)
|
|
111
|
-
self._session.current_recursion_depth += 1
|
|
112
|
-
|
|
113
|
-
def pop_recursive_context(self) -> Optional[dict[str, Any]]:
|
|
114
|
-
"""Pop the current context from the recursive execution stack."""
|
|
115
|
-
if self._session.recursive_context_stack:
|
|
116
|
-
self._session.current_recursion_depth = max(
|
|
117
|
-
0, self._session.current_recursion_depth - 1
|
|
118
|
-
)
|
|
119
|
-
return self._session.recursive_context_stack.pop()
|
|
120
|
-
return None
|
|
121
|
-
|
|
122
|
-
def set_task_iteration_budget(self, task_id: str, budget: int) -> None:
|
|
123
|
-
"""Set the iteration budget for a specific task."""
|
|
124
|
-
self._session.iteration_budgets[task_id] = budget
|
|
125
|
-
|
|
126
|
-
def get_task_iteration_budget(self, task_id: str) -> int:
|
|
127
|
-
"""Get the iteration budget for a specific task."""
|
|
128
|
-
return self._session.iteration_budgets.get(task_id, 10) # Default to 10
|
|
129
|
-
|
|
130
|
-
def can_recurse_deeper(self) -> bool:
|
|
131
|
-
"""Check if we can recurse deeper without exceeding limits."""
|
|
132
|
-
return self._session.current_recursion_depth < self._session.max_recursion_depth
|
|
133
|
-
|
|
134
|
-
def reset_recursive_state(self) -> None:
|
|
135
|
-
"""Reset all recursive execution state."""
|
|
136
|
-
self._session.current_recursion_depth = 0
|
|
137
|
-
self._session.parent_task_id = None
|
|
138
|
-
self._session.task_hierarchy.clear()
|
|
139
|
-
self._session.iteration_budgets.clear()
|
|
140
|
-
self._session.recursive_context_stack.clear()
|
|
141
|
-
|
|
142
101
|
def remove_todo(self, todo_id: str) -> None:
|
|
143
102
|
self._session.todos = [todo for todo in self._session.todos if todo.id != todo_id]
|
|
144
103
|
|
tunacode/exceptions.py
CHANGED
|
@@ -114,26 +114,3 @@ class TooBroadPatternError(ToolExecutionError):
|
|
|
114
114
|
f"Pattern '{pattern}' is too broad - no matches found within {timeout_seconds}s. "
|
|
115
115
|
"Please use a more specific pattern.",
|
|
116
116
|
)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
class ToolBatchingJSONError(TunaCodeError):
|
|
120
|
-
"""Raised when JSON parsing fails during tool batching after all retries are exhausted."""
|
|
121
|
-
|
|
122
|
-
def __init__(
|
|
123
|
-
self,
|
|
124
|
-
json_content: str,
|
|
125
|
-
retry_count: int,
|
|
126
|
-
original_error: OriginalError = None,
|
|
127
|
-
):
|
|
128
|
-
self.json_content = json_content
|
|
129
|
-
self.retry_count = retry_count
|
|
130
|
-
self.original_error = original_error
|
|
131
|
-
|
|
132
|
-
# Truncate JSON content for display if too long
|
|
133
|
-
display_content = json_content[:100] + "..." if len(json_content) > 100 else json_content
|
|
134
|
-
|
|
135
|
-
super().__init__(
|
|
136
|
-
f"The model is having issues with tool batching. "
|
|
137
|
-
f"JSON parsing failed after {retry_count} retries. "
|
|
138
|
-
f"Invalid JSON: {display_content}"
|
|
139
|
-
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# DSPy Task Planning Prompt
|
|
2
|
+
|
|
3
|
+
This prompt is automatically generated and optimized by DSPy for TunaCode's complex task planning.
|
|
4
|
+
|
|
5
|
+
## Format
|
|
6
|
+
|
|
7
|
+
Given the fields `complex_request`, produce the fields `subtasks_with_tools`, `total_tool_calls`, `requires_todo`, `parallelization_opportunities`.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Follow the following format.
|
|
12
|
+
|
|
13
|
+
Complex Request: A complex task that needs breakdown
|
|
14
|
+
Reasoning: Let's think step by step in order to ${produce the answer}. We need to break this down into manageable subtasks...
|
|
15
|
+
Subtasks With Tools: JSON array of {task, tools, priority} objects
|
|
16
|
+
Total Tool Calls: Estimated total number of tool calls
|
|
17
|
+
Requires Todo: Whether todo tool should be used
|
|
18
|
+
Parallelization Opportunities: Number of parallel execution opportunities
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Learned Example (Selected by DSPy)
|
|
23
|
+
|
|
24
|
+
### Example: Authentication System Implementation
|
|
25
|
+
Complex Request: Implement user authentication system with JWT tokens
|
|
26
|
+
Reasoning: Let's think step by step. This is a complex implementation task that requires multiple components. First, I need to analyze the current application structure to understand how to integrate authentication. Then I'll design the user model and database schema. Next, I'll create the authentication endpoints for registration and login. I'll need to implement JWT token generation and validation. Finally, I'll add tests to ensure everything works correctly. Several of these tasks can be done in parallel once the initial analysis is complete.
|
|
27
|
+
Subtasks With Tools: [{"task": "Analyze current app structure", "tools": ["list_dir", "grep", "read_file"], "priority": "high"}, {"task": "Design user model", "tools": ["write_file"], "priority": "high"}, {"task": "Create auth endpoints", "tools": ["write_file", "update_file"], "priority": "high"}, {"task": "Add JWT tokens", "tools": ["write_file", "grep"], "priority": "high"}, {"task": "Write tests", "tools": ["write_file", "run_command"], "priority": "medium"}]
|
|
28
|
+
Total Tool Calls: 15
|
|
29
|
+
Requires Todo: true
|
|
30
|
+
Parallelization Opportunities: 3
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Key Patterns for Complex Tasks
|
|
35
|
+
|
|
36
|
+
1. **Break Down First**: Start with analysis/exploration before implementation
|
|
37
|
+
2. **Priority Levels**: High for core functionality, medium for tests/docs, low for nice-to-haves
|
|
38
|
+
3. **Tool Grouping**: Group related tools together for each subtask
|
|
39
|
+
4. **Todo Usage**: Use todo tool for tasks with 5+ subtasks
|
|
40
|
+
5. **Parallelization**: Identify independent subtasks that can run concurrently
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
Complex Request: ${complex_request}
|
|
45
|
+
Reasoning: Let's think step by step...
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# DSPy Tool Selection Prompt
|
|
2
|
+
|
|
3
|
+
This prompt is automatically generated and optimized by DSPy for TunaCode's tool selection.
|
|
4
|
+
|
|
5
|
+
## Format
|
|
6
|
+
|
|
7
|
+
Given the fields `user_request`, `current_directory`, produce the fields `tools_json`, `requires_confirmation`, `reasoning`.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Follow the following format.
|
|
12
|
+
|
|
13
|
+
User Request: The user's request or task
|
|
14
|
+
Current Directory: Current working directory context
|
|
15
|
+
Reasoning: Let's think step by step in order to ${produce the answer}. We ...
|
|
16
|
+
Tools Json: JSON array of tool calls with batch grouping, e.g. [[tool1, tool2, tool3], [tool4]]
|
|
17
|
+
Requires Confirmation: Whether any tools require user confirmation
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Learned Examples (Automatically Selected by DSPy)
|
|
22
|
+
|
|
23
|
+
### Example 1: Searching for Implementation
|
|
24
|
+
User Request: Show me the authentication system implementation
|
|
25
|
+
Current Directory: .
|
|
26
|
+
Reasoning: Let's think step by step. To show the authentication implementation, I need to search for auth-related files across the codebase. I'll use grep to find files containing 'auth', list the auth directory if it exists, and use glob to find all auth-related Python files. These are all read-only operations that can be executed in parallel.
|
|
27
|
+
Tools Json: [["grep(\"auth\", \"src/\")", "list_dir(\"src/auth/\")", "glob(\"**/*auth*.py\")"]]
|
|
28
|
+
Requires Confirmation: false
|
|
29
|
+
|
|
30
|
+
### Example 2: Reading Multiple Files (Optimal Batching)
|
|
31
|
+
User Request: Read all config files and the main module
|
|
32
|
+
Current Directory: .
|
|
33
|
+
Reasoning: Let's think step by step. I need to read multiple specific files. All of these are read operations that can be batched together for parallel execution. I'll batch them in a group of 4 for optimal performance.
|
|
34
|
+
Tools Json: [["read_file(\"config.json\")", "read_file(\"settings.py\")", "read_file(\".env\")", "read_file(\"main.py\")"]]
|
|
35
|
+
Requires Confirmation: false
|
|
36
|
+
|
|
37
|
+
### Example 3: Search, Read, then Modify Pattern
|
|
38
|
+
User Request: Find the bug in validation and fix it
|
|
39
|
+
Current Directory: .
|
|
40
|
+
Reasoning: Let's think step by step. First, I need to search for validation-related code and errors. I'll use grep to search for error patterns and validation code, and list the validators directory. These search operations can be parallelized. After finding the issue, I'll need to read the specific file and then update it to fix the bug.
|
|
41
|
+
Tools Json: [["grep(\"error\", \"logs/\")", "grep(\"validation\", \"src/\")", "list_dir(\"src/validators/\")"], ["read_file(\"src/validators/user.py\")"], ["update_file(\"src/validators/user.py\", \"old\", \"new\")"]]
|
|
42
|
+
Requires Confirmation: true
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Key Patterns Learned by DSPy
|
|
47
|
+
|
|
48
|
+
1. **3-4 Tool Batching**: Optimal batch size for parallel read-only operations
|
|
49
|
+
2. **Read-Only Parallelization**: grep, list_dir, glob, read_file can run in parallel
|
|
50
|
+
3. **Sequential Writes**: write_file, update_file, run_command, bash must run sequentially
|
|
51
|
+
4. **Confirmation Required**: Any write/execute operation needs confirmation
|
|
52
|
+
5. **Search → Read → Modify**: Common pattern for debugging and fixes
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
User Request: ${user_request}
|
|
57
|
+
Current Directory: ${current_directory}
|
|
58
|
+
Reasoning: Let's think step by step...
|
tunacode/ui/input.py
CHANGED
|
@@ -75,13 +75,12 @@ async def multiline_input(
|
|
|
75
75
|
state_manager: Optional[StateManager] = None, command_registry=None
|
|
76
76
|
) -> str:
|
|
77
77
|
"""Get multiline input from the user with @file completion and highlighting."""
|
|
78
|
-
kb = create_key_bindings(
|
|
78
|
+
kb = create_key_bindings()
|
|
79
79
|
placeholder = formatted_text(
|
|
80
80
|
(
|
|
81
81
|
"<darkgrey>"
|
|
82
82
|
"<bold>Enter</bold> to submit • "
|
|
83
83
|
"<bold>Esc + Enter</bold> for new line • "
|
|
84
|
-
"<bold>Esc</bold> to cancel • "
|
|
85
84
|
"<bold>/help</bold> for commands"
|
|
86
85
|
"</darkgrey>"
|
|
87
86
|
)
|
tunacode/ui/keybindings.py
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
"""Key binding handlers for TunaCode UI."""
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
3
|
from prompt_toolkit.key_binding import KeyBindings
|
|
6
4
|
|
|
7
|
-
from ..core.state import StateManager
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
5
|
|
|
11
|
-
|
|
12
|
-
def create_key_bindings(state_manager: StateManager = None) -> KeyBindings:
|
|
6
|
+
def create_key_bindings() -> KeyBindings:
|
|
13
7
|
"""Create and configure key bindings for the UI."""
|
|
14
8
|
kb = KeyBindings()
|
|
15
9
|
|
|
@@ -28,14 +22,4 @@ def create_key_bindings(state_manager: StateManager = None) -> KeyBindings:
|
|
|
28
22
|
"""Insert a newline when escape then enter is pressed."""
|
|
29
23
|
event.current_buffer.insert_text("\n")
|
|
30
24
|
|
|
31
|
-
@kb.add("escape")
|
|
32
|
-
def _escape(event):
|
|
33
|
-
"""Immediately interrupts the current operation."""
|
|
34
|
-
current_task = state_manager.session.current_task if state_manager else None
|
|
35
|
-
if current_task and not current_task.done():
|
|
36
|
-
logger.debug("Interrupting current task")
|
|
37
|
-
current_task.cancel()
|
|
38
|
-
else:
|
|
39
|
-
logger.debug("Escape key pressed outside task context")
|
|
40
|
-
|
|
41
25
|
return kb
|
tunacode/ui/panels.py
CHANGED
|
@@ -9,7 +9,6 @@ from rich.padding import Padding
|
|
|
9
9
|
from rich.panel import Panel
|
|
10
10
|
from rich.pretty import Pretty
|
|
11
11
|
from rich.table import Table
|
|
12
|
-
from rich.text import Text
|
|
13
12
|
|
|
14
13
|
from tunacode.configuration.models import ModelRegistry
|
|
15
14
|
from tunacode.constants import (
|
|
@@ -90,15 +89,9 @@ class StreamingAgentPanel:
|
|
|
90
89
|
# Use the UI_THINKING_MESSAGE constant instead of hardcoded text
|
|
91
90
|
from tunacode.constants import UI_THINKING_MESSAGE
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
if not self.content:
|
|
95
|
-
content_to_display = Text.from_markup(UI_THINKING_MESSAGE)
|
|
96
|
-
else:
|
|
97
|
-
# Normal content is markdown
|
|
98
|
-
content_to_display = Markdown(self.content)
|
|
99
|
-
|
|
92
|
+
markdown_content = Markdown(self.content or UI_THINKING_MESSAGE)
|
|
100
93
|
panel_obj = Panel(
|
|
101
|
-
Padding(
|
|
94
|
+
Padding(markdown_content, (0, 1, 0, 1)),
|
|
102
95
|
title=f"[bold]{self.title}[/bold]",
|
|
103
96
|
title_align="left",
|
|
104
97
|
border_style=colors.primary,
|
tunacode/utils/token_counter.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tunacode-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.48
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Author-email: larock22 <noreply@github.com>
|
|
6
6
|
License: MIT
|
|
@@ -37,7 +37,7 @@ Requires-Dist: textual-dev; extra == "dev"
|
|
|
37
37
|
Requires-Dist: pre-commit; extra == "dev"
|
|
38
38
|
Dynamic: license-file
|
|
39
39
|
|
|
40
|
-
# TunaCode
|
|
40
|
+
# TunaCode CLI
|
|
41
41
|
|
|
42
42
|
<div align="center">
|
|
43
43
|
|
|
@@ -48,7 +48,7 @@ Dynamic: license-file
|
|
|
48
48
|
|
|
49
49
|
**AI-powered CLI coding assistant**
|
|
50
50
|
|
|
51
|
-

|
|
52
52
|
|
|
53
53
|
</div>
|
|
54
54
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
tunacode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
tunacode/constants.py,sha256=
|
|
2
|
+
tunacode/constants.py,sha256=SnkxDDf4YNG66RWs2ByAN5aIZra8ubkzlXv5-OE1ZZU,4993
|
|
3
3
|
tunacode/context.py,sha256=_gXVCyjU052jlyRAl9tklZSwl5U_zI_EIX8XN87VVWE,2786
|
|
4
|
-
tunacode/exceptions.py,sha256=
|
|
4
|
+
tunacode/exceptions.py,sha256=mTWXuWyr1k16CGLWN2tsthDGi7lbx1JK0ekIqogYDP8,3105
|
|
5
5
|
tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
tunacode/setup.py,sha256=XPt4eAK-qcIZQv64jGZ_ryxcImDwps9OmXjJfIS1xcs,1899
|
|
7
7
|
tunacode/types.py,sha256=Czq7jYXHq7fZQtyqkCN5_7eEu1wyYUcB50C6v3sTWDw,8188
|
|
8
8
|
tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
|
|
9
|
-
tunacode/cli/main.py,sha256=
|
|
10
|
-
tunacode/cli/repl.py,sha256=
|
|
9
|
+
tunacode/cli/main.py,sha256=ypefhvSt9hXzNOv0WpR-PlkUOSGadvcFbUIRT13n9oo,2619
|
|
10
|
+
tunacode/cli/repl.py,sha256=CMvl5wlxj7hr45mxil26fwbmWpDYxRsRVS9aIGJvKK0,18525
|
|
11
11
|
tunacode/cli/commands/__init__.py,sha256=zmE9JcJ9Qd2xJhgdS4jMDJOoZsrAZmL5MAFxbKkk7F8,1670
|
|
12
12
|
tunacode/cli/commands/base.py,sha256=GxUuDsDSpz0iXryy8MrEw88UM3C3yxL__kDK1QhshoA,2517
|
|
13
13
|
tunacode/cli/commands/registry.py,sha256=XVuLpp5S4Fw7GfIZfLrVZFo4jMLMNmYNpYN7xWgXyOk,8223
|
|
@@ -19,25 +19,21 @@ tunacode/cli/commands/implementations/model.py,sha256=uthx6IX9KwgwywNTDklkJpqCba
|
|
|
19
19
|
tunacode/cli/commands/implementations/system.py,sha256=2cGw5iCJO3aNhXTFF28CgAIyLgslvHmpfyL2ZHVB6oQ,7903
|
|
20
20
|
tunacode/cli/commands/implementations/todo.py,sha256=Dtz5bgcuK2VXGPWEBBZQgnWUMYkRXNzTGf_qkVPLF2U,8125
|
|
21
21
|
tunacode/configuration/__init__.py,sha256=MbVXy8bGu0yKehzgdgZ_mfWlYGvIdb1dY2Ly75nfuPE,17
|
|
22
|
-
tunacode/configuration/defaults.py,sha256=
|
|
22
|
+
tunacode/configuration/defaults.py,sha256=Qny32BhbSeRBrE9baWZcAit3XFXgWuXFMDJUZudj55M,922
|
|
23
23
|
tunacode/configuration/models.py,sha256=buH8ZquvcYI3OQBDIZeJ08cu00rSCeNABtUwl3VQS0E,4103
|
|
24
24
|
tunacode/configuration/settings.py,sha256=KoN0u6GG3Hh_TWt02D_wpRfbACYri3gCDTXHtJfHl2w,994
|
|
25
25
|
tunacode/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
tunacode/core/code_index.py,sha256=jgAx3lSWP_DwnyiP5Jkm1YvX4JJyI4teMzlNrJSpEOA,15661
|
|
27
|
-
tunacode/core/state.py,sha256=
|
|
27
|
+
tunacode/core/state.py,sha256=hOLuvojJksd3GEezNT6jLPAsCcI-mZKldUUvlP4IKjw,3641
|
|
28
28
|
tunacode/core/tool_handler.py,sha256=BPjR013OOO0cLXPdLeL2FDK0ixUwOYu59FfHdcdFhp4,2277
|
|
29
29
|
tunacode/core/agents/__init__.py,sha256=UUJiPYb91arwziSpjd7vIk7XNGA_4HQbsOIbskSqevA,149
|
|
30
|
-
tunacode/core/agents/
|
|
31
|
-
tunacode/core/agents/
|
|
30
|
+
tunacode/core/agents/dspy_integration.py,sha256=h3gJ-qr0fXpB2CRaU-MVv_8xG--ah-8nra7WO960Gbo,9152
|
|
31
|
+
tunacode/core/agents/dspy_tunacode.py,sha256=tIluqDsHAv3nbNYtqFh4oyZA9yqMrnyY2G-QOpkTLCs,17398
|
|
32
|
+
tunacode/core/agents/main.py,sha256=UOMJTkuhMEMVmV0bGWU2cEkiukdcLAKby-9AOaIGc0Y,43102
|
|
33
|
+
tunacode/core/agents/utils.py,sha256=VaNsPB2l1dAP-VlS_QLRKvCb4NW0pXNRoxkh12AGXAg,10744
|
|
32
34
|
tunacode/core/background/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
35
|
tunacode/core/background/manager.py,sha256=rJdl3eDLTQwjbT7VhxXcJbZopCNR3M8ZGMbmeVnwwMc,1126
|
|
34
36
|
tunacode/core/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
tunacode/core/recursive/__init__.py,sha256=S9_dN0faJqam3Pnaum9PRC8Hd90bpES8syFgAD8-QbI,446
|
|
36
|
-
tunacode/core/recursive/aggregator.py,sha256=KlWajEyT8OokWeY6ZwQ4EsVu05V4KeH3o2cYUz-Ce1Y,15725
|
|
37
|
-
tunacode/core/recursive/budget.py,sha256=0wY6xSrZKmudUwthwX1mlcF5yat2_y3fNu5shX_IzvA,14131
|
|
38
|
-
tunacode/core/recursive/decomposer.py,sha256=k8rgaPEMMb2mZ9W0m_Yg0oEBqbYpqDnK0zyTkx6eTPs,14550
|
|
39
|
-
tunacode/core/recursive/executor.py,sha256=7taFsjYjSfL8OUQLM1ZVn9Xix7YoputFBAZSo9tDtDM,16646
|
|
40
|
-
tunacode/core/recursive/hierarchy.py,sha256=67tdDCKB5mTSn6VIwm-knEHB_VKUkeljFdwH62U5chE,15648
|
|
41
37
|
tunacode/core/setup/__init__.py,sha256=lzdpY6rIGf9DDlDBDGFvQZaSOQeFsNglHbkpq1-GtU8,376
|
|
42
38
|
tunacode/core/setup/agent_setup.py,sha256=trELO8cPnWo36BBnYmXDEnDPdhBg0p-VLnx9A8hSSSQ,1401
|
|
43
39
|
tunacode/core/setup/base.py,sha256=cbyT2-xK2mWgH4EO17VfM_OM2bj0kT895NW2jSXbe3c,968
|
|
@@ -48,6 +44,8 @@ tunacode/core/setup/git_safety_setup.py,sha256=CRIqrQt0QUJQRS344njty_iCqTorrDhHl
|
|
|
48
44
|
tunacode/core/token_usage/api_response_parser.py,sha256=CTtqGaFaxpkzkW3TEbe00QJzyRULpWN1EQxIYMleseg,1622
|
|
49
45
|
tunacode/core/token_usage/cost_calculator.py,sha256=RjO-O0JENBuGOrWP7QgBZlZxeXC-PAIr8tj_9p_BxOU,2058
|
|
50
46
|
tunacode/core/token_usage/usage_tracker.py,sha256=kuAjUCyQkFykPy5mqsLRbKhZW298pyiCuFGn-ptBpy4,4657
|
|
47
|
+
tunacode/prompts/dspy_task_planning.md,sha256=RNimkmnFcNgskwQrguGb3wB8A-Zngp6Qc9lXfPj61OU,2512
|
|
48
|
+
tunacode/prompts/dspy_tool_selection.md,sha256=CPBHrI4QlWD2mzNdoVkFK7GydgCLW9Bi20sD8ZEysRo,3070
|
|
51
49
|
tunacode/prompts/system.md,sha256=hXpjZ8Yiv2Acr2_6EmC2uOklP8FbmvyYR9oais-1KLk,16290
|
|
52
50
|
tunacode/services/__init__.py,sha256=w_E8QK6RnvKSvU866eDe8BCRV26rAm4d3R-Yg06OWCU,19
|
|
53
51
|
tunacode/services/mcp.py,sha256=R48X73KQjQ9vwhBrtbWHSBl-4K99QXmbIhh5J_1Gezo,3046
|
|
@@ -68,13 +66,12 @@ tunacode/ui/completers.py,sha256=Jx1zyCESwdm_4ZopvCBtb0bCJF-bRy8aBWG2yhPQtDc,487
|
|
|
68
66
|
tunacode/ui/console.py,sha256=icb7uYrV8XmZg9glreEy5MrvDkmrKxbf_ZkNqElN1uE,2120
|
|
69
67
|
tunacode/ui/constants.py,sha256=A76B_KpM8jCuBYRg4cPmhi8_j6LLyWttO7_jjv47r3w,421
|
|
70
68
|
tunacode/ui/decorators.py,sha256=e2KM-_pI5EKHa2M045IjUe4rPkTboxaKHXJT0K3461g,1914
|
|
71
|
-
tunacode/ui/input.py,sha256=
|
|
72
|
-
tunacode/ui/keybindings.py,sha256=
|
|
69
|
+
tunacode/ui/input.py,sha256=E_zAJqNYoAVFA-j4xE9Qgs22y-GrdSZNqiseX-Or0ho,2955
|
|
70
|
+
tunacode/ui/keybindings.py,sha256=h0MlD73CW_3i2dQzb9EFSPkqy0raZ_isgjxUiA9u6ts,691
|
|
73
71
|
tunacode/ui/lexers.py,sha256=tmg4ic1enyTRLzanN5QPP7D_0n12YjX_8ZhsffzhXA4,1340
|
|
74
72
|
tunacode/ui/output.py,sha256=51O0VHajte4dXHK5Az5SSP4IOb2q5SbCwvqdAoxyg7c,5665
|
|
75
|
-
tunacode/ui/panels.py,sha256=
|
|
73
|
+
tunacode/ui/panels.py,sha256=ckL-TYxYWlpBAFj8SC9Od8vrW7Kf5N92bZRYBWR14jE,8338
|
|
76
74
|
tunacode/ui/prompt_manager.py,sha256=U2cntB34vm-YwOj3gzFRUK362zccrz8pigQfpxr5sv8,4650
|
|
77
|
-
tunacode/ui/recursive_progress.py,sha256=V0dGpJWt19TVArOYcQ3Lki8cR3ZepFT6iGwnChSFhFI,12906
|
|
78
75
|
tunacode/ui/tool_ui.py,sha256=qp1aZUpLO5UOdJziY8tw0URC8gjoWoSKdGu5y2wuTUU,7013
|
|
79
76
|
tunacode/ui/utils.py,sha256=yvoCTz8AOdRfV0XIqUX3sgg88g_wntV9yhnQP6WzAVs,114
|
|
80
77
|
tunacode/ui/validators.py,sha256=MMIMT1I2v0l2jIy-gxX_4GSApvUTi8XWIOACr_dmoBA,758
|
|
@@ -84,16 +81,15 @@ tunacode/utils/diff_utils.py,sha256=V9QqQ0q4MfabVTnWptF3IXDp3estnfOKcJtDe_Sj14I,
|
|
|
84
81
|
tunacode/utils/file_utils.py,sha256=AXiAJ_idtlmXEi9pMvwtfPy9Ys3yK-F4K7qb_NpwonU,923
|
|
85
82
|
tunacode/utils/import_cache.py,sha256=q_xjJbtju05YbFopLDSkIo1hOtCx3DOTl3GQE5FFDgs,295
|
|
86
83
|
tunacode/utils/message_utils.py,sha256=kM6VSS2Dudjplie009khHgmIRjDoBUzv6tvHcYNDAAE,586
|
|
87
|
-
tunacode/utils/retry.py,sha256=AHdUzY6m-mwlT4OPXdtWWMAafL_NeS7JAMORGyM8c5k,4931
|
|
88
84
|
tunacode/utils/ripgrep.py,sha256=AXUs2FFt0A7KBV996deS8wreIlUzKOlAHJmwrcAr4No,583
|
|
89
85
|
tunacode/utils/security.py,sha256=e_zo9VmcOKFjgFMr9GOBIFhAmND4PBlJZgY7zqnsGjI,6548
|
|
90
86
|
tunacode/utils/system.py,sha256=FSoibTIH0eybs4oNzbYyufIiV6gb77QaeY2yGqW39AY,11381
|
|
91
87
|
tunacode/utils/text_utils.py,sha256=6YBD9QfkDO44-6jxnwRWIpmfIifPG-NqMzy_O2NAouc,7277
|
|
92
|
-
tunacode/utils/token_counter.py,sha256=
|
|
88
|
+
tunacode/utils/token_counter.py,sha256=l5KemYLfsypAtAF_YrDtVKFtBEghydS_MA8c-8mpPvM,2721
|
|
93
89
|
tunacode/utils/user_configuration.py,sha256=Ilz8dpGVJDBE2iLWHAPT0xR8D51VRKV3kIbsAz8Bboc,3275
|
|
94
|
-
tunacode_cli-0.0.
|
|
95
|
-
tunacode_cli-0.0.
|
|
96
|
-
tunacode_cli-0.0.
|
|
97
|
-
tunacode_cli-0.0.
|
|
98
|
-
tunacode_cli-0.0.
|
|
99
|
-
tunacode_cli-0.0.
|
|
90
|
+
tunacode_cli-0.0.48.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
91
|
+
tunacode_cli-0.0.48.dist-info/METADATA,sha256=JGqtbkLjVdJIz9glj3II8lPbNj2kXvXQdrpjra2z-Nw,5887
|
|
92
|
+
tunacode_cli-0.0.48.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
93
|
+
tunacode_cli-0.0.48.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
|
|
94
|
+
tunacode_cli-0.0.48.dist-info/top_level.txt,sha256=lKy2P6BWNi5XSA4DHFvyjQ14V26lDZctwdmhEJrxQbU,9
|
|
95
|
+
tunacode_cli-0.0.48.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"""Module: tunacode.core.recursive
|
|
2
|
-
|
|
3
|
-
Recursive task execution system for complex task decomposition and execution.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from .aggregator import ResultAggregator
|
|
7
|
-
from .budget import BudgetManager
|
|
8
|
-
from .decomposer import TaskDecomposer
|
|
9
|
-
from .executor import RecursiveTaskExecutor
|
|
10
|
-
from .hierarchy import TaskHierarchy
|
|
11
|
-
|
|
12
|
-
__all__ = [
|
|
13
|
-
"RecursiveTaskExecutor",
|
|
14
|
-
"TaskDecomposer",
|
|
15
|
-
"TaskHierarchy",
|
|
16
|
-
"BudgetManager",
|
|
17
|
-
"ResultAggregator",
|
|
18
|
-
]
|