tunacode-cli 0.1.21__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/__init__.py +0 -0
- tunacode/cli/textual_repl.tcss +283 -0
- tunacode/configuration/__init__.py +1 -0
- tunacode/configuration/defaults.py +45 -0
- tunacode/configuration/models.py +147 -0
- tunacode/configuration/models_registry.json +1 -0
- tunacode/configuration/pricing.py +74 -0
- tunacode/configuration/settings.py +35 -0
- tunacode/constants.py +227 -0
- tunacode/core/__init__.py +6 -0
- tunacode/core/agents/__init__.py +39 -0
- tunacode/core/agents/agent_components/__init__.py +48 -0
- tunacode/core/agents/agent_components/agent_config.py +441 -0
- tunacode/core/agents/agent_components/agent_helpers.py +290 -0
- tunacode/core/agents/agent_components/message_handler.py +99 -0
- tunacode/core/agents/agent_components/node_processor.py +477 -0
- tunacode/core/agents/agent_components/response_state.py +129 -0
- tunacode/core/agents/agent_components/result_wrapper.py +51 -0
- tunacode/core/agents/agent_components/state_transition.py +112 -0
- tunacode/core/agents/agent_components/streaming.py +271 -0
- tunacode/core/agents/agent_components/task_completion.py +40 -0
- tunacode/core/agents/agent_components/tool_buffer.py +44 -0
- tunacode/core/agents/agent_components/tool_executor.py +101 -0
- tunacode/core/agents/agent_components/truncation_checker.py +37 -0
- tunacode/core/agents/delegation_tools.py +109 -0
- tunacode/core/agents/main.py +545 -0
- tunacode/core/agents/prompts.py +66 -0
- tunacode/core/agents/research_agent.py +231 -0
- tunacode/core/compaction.py +218 -0
- tunacode/core/prompting/__init__.py +27 -0
- tunacode/core/prompting/loader.py +66 -0
- tunacode/core/prompting/prompting_engine.py +98 -0
- tunacode/core/prompting/sections.py +50 -0
- tunacode/core/prompting/templates.py +69 -0
- tunacode/core/state.py +409 -0
- tunacode/exceptions.py +313 -0
- tunacode/indexing/__init__.py +5 -0
- tunacode/indexing/code_index.py +432 -0
- tunacode/indexing/constants.py +86 -0
- tunacode/lsp/__init__.py +112 -0
- tunacode/lsp/client.py +351 -0
- tunacode/lsp/diagnostics.py +19 -0
- tunacode/lsp/servers.py +101 -0
- tunacode/prompts/default_prompt.md +952 -0
- tunacode/prompts/research/sections/agent_role.xml +5 -0
- tunacode/prompts/research/sections/constraints.xml +14 -0
- tunacode/prompts/research/sections/output_format.xml +57 -0
- tunacode/prompts/research/sections/tool_use.xml +23 -0
- tunacode/prompts/sections/advanced_patterns.xml +255 -0
- tunacode/prompts/sections/agent_role.xml +8 -0
- tunacode/prompts/sections/completion.xml +10 -0
- tunacode/prompts/sections/critical_rules.xml +37 -0
- tunacode/prompts/sections/examples.xml +220 -0
- tunacode/prompts/sections/output_style.xml +94 -0
- tunacode/prompts/sections/parallel_exec.xml +105 -0
- tunacode/prompts/sections/search_pattern.xml +100 -0
- tunacode/prompts/sections/system_info.xml +6 -0
- tunacode/prompts/sections/tool_use.xml +84 -0
- tunacode/prompts/sections/user_instructions.xml +3 -0
- tunacode/py.typed +0 -0
- tunacode/templates/__init__.py +5 -0
- tunacode/templates/loader.py +15 -0
- tunacode/tools/__init__.py +10 -0
- tunacode/tools/authorization/__init__.py +29 -0
- tunacode/tools/authorization/context.py +32 -0
- tunacode/tools/authorization/factory.py +20 -0
- tunacode/tools/authorization/handler.py +58 -0
- tunacode/tools/authorization/notifier.py +35 -0
- tunacode/tools/authorization/policy.py +19 -0
- tunacode/tools/authorization/requests.py +119 -0
- tunacode/tools/authorization/rules.py +72 -0
- tunacode/tools/bash.py +222 -0
- tunacode/tools/decorators.py +213 -0
- tunacode/tools/glob.py +353 -0
- tunacode/tools/grep.py +468 -0
- tunacode/tools/grep_components/__init__.py +9 -0
- tunacode/tools/grep_components/file_filter.py +93 -0
- tunacode/tools/grep_components/pattern_matcher.py +158 -0
- tunacode/tools/grep_components/result_formatter.py +87 -0
- tunacode/tools/grep_components/search_result.py +34 -0
- tunacode/tools/list_dir.py +205 -0
- tunacode/tools/prompts/bash_prompt.xml +10 -0
- tunacode/tools/prompts/glob_prompt.xml +7 -0
- tunacode/tools/prompts/grep_prompt.xml +10 -0
- tunacode/tools/prompts/list_dir_prompt.xml +7 -0
- tunacode/tools/prompts/read_file_prompt.xml +9 -0
- tunacode/tools/prompts/todoclear_prompt.xml +12 -0
- tunacode/tools/prompts/todoread_prompt.xml +16 -0
- tunacode/tools/prompts/todowrite_prompt.xml +28 -0
- tunacode/tools/prompts/update_file_prompt.xml +9 -0
- tunacode/tools/prompts/web_fetch_prompt.xml +11 -0
- tunacode/tools/prompts/write_file_prompt.xml +7 -0
- tunacode/tools/react.py +111 -0
- tunacode/tools/read_file.py +68 -0
- tunacode/tools/todo.py +222 -0
- tunacode/tools/update_file.py +62 -0
- tunacode/tools/utils/__init__.py +1 -0
- tunacode/tools/utils/ripgrep.py +311 -0
- tunacode/tools/utils/text_match.py +352 -0
- tunacode/tools/web_fetch.py +245 -0
- tunacode/tools/write_file.py +34 -0
- tunacode/tools/xml_helper.py +34 -0
- tunacode/types/__init__.py +166 -0
- tunacode/types/base.py +94 -0
- tunacode/types/callbacks.py +53 -0
- tunacode/types/dataclasses.py +121 -0
- tunacode/types/pydantic_ai.py +31 -0
- tunacode/types/state.py +122 -0
- tunacode/ui/__init__.py +6 -0
- tunacode/ui/app.py +542 -0
- tunacode/ui/commands/__init__.py +430 -0
- tunacode/ui/components/__init__.py +1 -0
- tunacode/ui/headless/__init__.py +5 -0
- tunacode/ui/headless/output.py +72 -0
- tunacode/ui/main.py +252 -0
- tunacode/ui/renderers/__init__.py +41 -0
- tunacode/ui/renderers/errors.py +197 -0
- tunacode/ui/renderers/panels.py +550 -0
- tunacode/ui/renderers/search.py +314 -0
- tunacode/ui/renderers/tools/__init__.py +21 -0
- tunacode/ui/renderers/tools/bash.py +247 -0
- tunacode/ui/renderers/tools/diagnostics.py +186 -0
- tunacode/ui/renderers/tools/glob.py +226 -0
- tunacode/ui/renderers/tools/grep.py +228 -0
- tunacode/ui/renderers/tools/list_dir.py +198 -0
- tunacode/ui/renderers/tools/read_file.py +226 -0
- tunacode/ui/renderers/tools/research.py +294 -0
- tunacode/ui/renderers/tools/update_file.py +237 -0
- tunacode/ui/renderers/tools/web_fetch.py +182 -0
- tunacode/ui/repl_support.py +226 -0
- tunacode/ui/screens/__init__.py +16 -0
- tunacode/ui/screens/model_picker.py +303 -0
- tunacode/ui/screens/session_picker.py +181 -0
- tunacode/ui/screens/setup.py +218 -0
- tunacode/ui/screens/theme_picker.py +90 -0
- tunacode/ui/screens/update_confirm.py +69 -0
- tunacode/ui/shell_runner.py +129 -0
- tunacode/ui/styles/layout.tcss +98 -0
- tunacode/ui/styles/modals.tcss +38 -0
- tunacode/ui/styles/panels.tcss +81 -0
- tunacode/ui/styles/theme-nextstep.tcss +303 -0
- tunacode/ui/styles/widgets.tcss +33 -0
- tunacode/ui/styles.py +18 -0
- tunacode/ui/widgets/__init__.py +23 -0
- tunacode/ui/widgets/command_autocomplete.py +62 -0
- tunacode/ui/widgets/editor.py +402 -0
- tunacode/ui/widgets/file_autocomplete.py +47 -0
- tunacode/ui/widgets/messages.py +46 -0
- tunacode/ui/widgets/resource_bar.py +182 -0
- tunacode/ui/widgets/status_bar.py +98 -0
- tunacode/utils/__init__.py +0 -0
- tunacode/utils/config/__init__.py +13 -0
- tunacode/utils/config/user_configuration.py +91 -0
- tunacode/utils/messaging/__init__.py +10 -0
- tunacode/utils/messaging/message_utils.py +34 -0
- tunacode/utils/messaging/token_counter.py +77 -0
- tunacode/utils/parsing/__init__.py +13 -0
- tunacode/utils/parsing/command_parser.py +55 -0
- tunacode/utils/parsing/json_utils.py +188 -0
- tunacode/utils/parsing/retry.py +146 -0
- tunacode/utils/parsing/tool_parser.py +267 -0
- tunacode/utils/security/__init__.py +15 -0
- tunacode/utils/security/command.py +106 -0
- tunacode/utils/system/__init__.py +25 -0
- tunacode/utils/system/gitignore.py +155 -0
- tunacode/utils/system/paths.py +190 -0
- tunacode/utils/ui/__init__.py +9 -0
- tunacode/utils/ui/file_filter.py +135 -0
- tunacode/utils/ui/helpers.py +24 -0
- tunacode_cli-0.1.21.dist-info/METADATA +170 -0
- tunacode_cli-0.1.21.dist-info/RECORD +174 -0
- tunacode_cli-0.1.21.dist-info/WHEEL +4 -0
- tunacode_cli-0.1.21.dist-info/entry_points.txt +2 -0
- tunacode_cli-0.1.21.dist-info/licenses/LICENSE +21 -0
tunacode/exceptions.py
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TunaCode CLI exception hierarchy.
|
|
3
|
+
|
|
4
|
+
This module defines all custom exceptions used throughout the TunaCode CLI.
|
|
5
|
+
All exceptions inherit from TunaCodeError for easy catching of any TunaCode-specific error.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from tunacode.types import ErrorMessage, FilePath, OriginalError, ToolName
|
|
9
|
+
|
|
10
|
+
SECTION_SEPARATOR = "\n\n"
|
|
11
|
+
LINE_SEPARATOR = "\n"
|
|
12
|
+
BULLET_PREFIX = " - "
|
|
13
|
+
NUMBERED_ITEM_PREFIX = " {index}. "
|
|
14
|
+
|
|
15
|
+
SUGGESTED_FIX_LABEL = "Suggested fix"
|
|
16
|
+
VALID_EXAMPLES_LABEL = "Valid examples"
|
|
17
|
+
RECOVERY_COMMANDS_LABEL = "Recovery commands"
|
|
18
|
+
TROUBLESHOOTING_STEPS_LABEL = "Troubleshooting steps"
|
|
19
|
+
HELP_LABEL = "More help"
|
|
20
|
+
|
|
21
|
+
VALIDATION_PREFIX = "Validation failed: "
|
|
22
|
+
AGENT_ERROR_PREFIX = "Agent error: "
|
|
23
|
+
TOOL_ERROR_PREFIX = "Tool '{tool_name}' failed: "
|
|
24
|
+
|
|
25
|
+
JSON_TRUNCATION_LIMIT = 100
|
|
26
|
+
VALID_MODEL_EXAMPLE_LIMIT = 3
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _format_section(label: str, lines: list[str]) -> str:
|
|
30
|
+
if not lines:
|
|
31
|
+
return ""
|
|
32
|
+
|
|
33
|
+
section_header = f"{label}:"
|
|
34
|
+
section_body = LINE_SEPARATOR.join(lines)
|
|
35
|
+
return f"{section_header}{LINE_SEPARATOR}{section_body}"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _build_error_message(
|
|
39
|
+
base_message: str,
|
|
40
|
+
suggested_fix: str | None = None,
|
|
41
|
+
help_url: str | None = None,
|
|
42
|
+
valid_examples: list[str] | None = None,
|
|
43
|
+
recovery_commands: list[str] | None = None,
|
|
44
|
+
troubleshooting_steps: list[str] | None = None,
|
|
45
|
+
) -> str:
|
|
46
|
+
sections: list[str] = []
|
|
47
|
+
|
|
48
|
+
if suggested_fix:
|
|
49
|
+
suggested_fix_section = _format_section(SUGGESTED_FIX_LABEL, [suggested_fix])
|
|
50
|
+
sections.append(suggested_fix_section)
|
|
51
|
+
|
|
52
|
+
if help_url:
|
|
53
|
+
help_section = _format_section(HELP_LABEL, [help_url])
|
|
54
|
+
sections.append(help_section)
|
|
55
|
+
|
|
56
|
+
if valid_examples:
|
|
57
|
+
example_lines = [f"{BULLET_PREFIX}{example}" for example in valid_examples]
|
|
58
|
+
examples_section = _format_section(VALID_EXAMPLES_LABEL, example_lines)
|
|
59
|
+
sections.append(examples_section)
|
|
60
|
+
|
|
61
|
+
if recovery_commands:
|
|
62
|
+
recovery_lines = [f"{BULLET_PREFIX}{cmd}" for cmd in recovery_commands]
|
|
63
|
+
recovery_section = _format_section(RECOVERY_COMMANDS_LABEL, recovery_lines)
|
|
64
|
+
sections.append(recovery_section)
|
|
65
|
+
|
|
66
|
+
if troubleshooting_steps:
|
|
67
|
+
step_lines = [
|
|
68
|
+
f"{NUMBERED_ITEM_PREFIX.format(index=i + 1)}{step}"
|
|
69
|
+
for i, step in enumerate(troubleshooting_steps)
|
|
70
|
+
]
|
|
71
|
+
troubleshooting_section = _format_section(TROUBLESHOOTING_STEPS_LABEL, step_lines)
|
|
72
|
+
sections.append(troubleshooting_section)
|
|
73
|
+
|
|
74
|
+
if not sections:
|
|
75
|
+
return base_message
|
|
76
|
+
|
|
77
|
+
sections_text = SECTION_SEPARATOR.join(sections)
|
|
78
|
+
return f"{base_message}{SECTION_SEPARATOR}{sections_text}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class TunaCodeError(Exception):
|
|
82
|
+
"""Base exception for all TunaCode errors."""
|
|
83
|
+
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ConfigurationError(TunaCodeError):
|
|
88
|
+
"""Raised when there's a configuration issue."""
|
|
89
|
+
|
|
90
|
+
def __init__(self, message: str, suggested_fix: str | None = None, help_url: str | None = None):
|
|
91
|
+
self.suggested_fix = suggested_fix
|
|
92
|
+
self.help_url = help_url
|
|
93
|
+
|
|
94
|
+
full_message = _build_error_message(
|
|
95
|
+
message,
|
|
96
|
+
suggested_fix=suggested_fix,
|
|
97
|
+
help_url=help_url,
|
|
98
|
+
)
|
|
99
|
+
super().__init__(full_message)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# User Interaction Exceptions
|
|
103
|
+
class UserAbortError(TunaCodeError):
|
|
104
|
+
"""Raised when user aborts an operation."""
|
|
105
|
+
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ValidationError(TunaCodeError):
|
|
110
|
+
"""Raised when input validation fails."""
|
|
111
|
+
|
|
112
|
+
def __init__(
|
|
113
|
+
self,
|
|
114
|
+
message: str,
|
|
115
|
+
suggested_fix: str | None = None,
|
|
116
|
+
valid_examples: list | None = None,
|
|
117
|
+
):
|
|
118
|
+
self.suggested_fix = suggested_fix
|
|
119
|
+
self.valid_examples = valid_examples or []
|
|
120
|
+
|
|
121
|
+
base_message = f"{VALIDATION_PREFIX}{message}"
|
|
122
|
+
full_message = _build_error_message(
|
|
123
|
+
base_message,
|
|
124
|
+
suggested_fix=suggested_fix,
|
|
125
|
+
valid_examples=self.valid_examples,
|
|
126
|
+
)
|
|
127
|
+
super().__init__(full_message)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# Tool and Agent Exceptions
|
|
131
|
+
class ToolExecutionError(TunaCodeError):
|
|
132
|
+
"""Raised when a tool fails to execute."""
|
|
133
|
+
|
|
134
|
+
def __init__(
|
|
135
|
+
self,
|
|
136
|
+
tool_name: ToolName,
|
|
137
|
+
message: ErrorMessage,
|
|
138
|
+
original_error: OriginalError = None,
|
|
139
|
+
suggested_fix: str | None = None,
|
|
140
|
+
recovery_commands: list | None = None,
|
|
141
|
+
):
|
|
142
|
+
self.tool_name = tool_name
|
|
143
|
+
self.original_error = original_error
|
|
144
|
+
self.suggested_fix = suggested_fix
|
|
145
|
+
self.recovery_commands = recovery_commands or []
|
|
146
|
+
|
|
147
|
+
base_message = TOOL_ERROR_PREFIX.format(tool_name=tool_name) + str(message)
|
|
148
|
+
full_message = _build_error_message(
|
|
149
|
+
base_message,
|
|
150
|
+
suggested_fix=suggested_fix,
|
|
151
|
+
recovery_commands=self.recovery_commands,
|
|
152
|
+
)
|
|
153
|
+
super().__init__(full_message)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class AgentError(TunaCodeError):
|
|
157
|
+
"""Raised when agent operations fail."""
|
|
158
|
+
|
|
159
|
+
def __init__(
|
|
160
|
+
self,
|
|
161
|
+
message: str,
|
|
162
|
+
suggested_fix: str | None = None,
|
|
163
|
+
troubleshooting_steps: list | None = None,
|
|
164
|
+
):
|
|
165
|
+
self.suggested_fix = suggested_fix
|
|
166
|
+
self.troubleshooting_steps = troubleshooting_steps or []
|
|
167
|
+
|
|
168
|
+
base_message = f"{AGENT_ERROR_PREFIX}{message}"
|
|
169
|
+
full_message = _build_error_message(
|
|
170
|
+
base_message,
|
|
171
|
+
suggested_fix=suggested_fix,
|
|
172
|
+
troubleshooting_steps=self.troubleshooting_steps,
|
|
173
|
+
)
|
|
174
|
+
super().__init__(full_message)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# State Management Exceptions
|
|
178
|
+
class StateError(TunaCodeError):
|
|
179
|
+
"""Raised when there's an issue with application state."""
|
|
180
|
+
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# External Service Exceptions
|
|
185
|
+
class ServiceError(TunaCodeError):
|
|
186
|
+
"""Base exception for external service failures."""
|
|
187
|
+
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class GitOperationError(ServiceError):
|
|
192
|
+
"""Raised when Git operations fail."""
|
|
193
|
+
|
|
194
|
+
def __init__(self, operation: str, message: ErrorMessage, original_error: OriginalError = None):
|
|
195
|
+
self.operation = operation
|
|
196
|
+
self.original_error = original_error
|
|
197
|
+
super().__init__(f"Git {operation} failed: {message}")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# File System Exceptions
|
|
201
|
+
class FileOperationError(TunaCodeError):
|
|
202
|
+
"""Raised when file system operations fail."""
|
|
203
|
+
|
|
204
|
+
def __init__(
|
|
205
|
+
self,
|
|
206
|
+
operation: str,
|
|
207
|
+
path: FilePath,
|
|
208
|
+
message: ErrorMessage,
|
|
209
|
+
original_error: OriginalError = None,
|
|
210
|
+
):
|
|
211
|
+
self.operation = operation
|
|
212
|
+
self.path = path
|
|
213
|
+
self.original_error = original_error
|
|
214
|
+
super().__init__(f"File {operation} failed for '{path}': {message}")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class ModelConfigurationError(ConfigurationError):
|
|
218
|
+
"""Raised when model configuration is invalid."""
|
|
219
|
+
|
|
220
|
+
def __init__(self, model: str, issue: str, valid_models: list | None = None):
|
|
221
|
+
self.model = model
|
|
222
|
+
self.issue = issue
|
|
223
|
+
self.valid_models = valid_models or []
|
|
224
|
+
|
|
225
|
+
suggested_fix = "Use --setup for guided setup or --model with a valid model name"
|
|
226
|
+
help_url = "https://docs.anthropic.com/en/docs/claude-code"
|
|
227
|
+
|
|
228
|
+
message = f"Model '{model}' configuration error: {issue}"
|
|
229
|
+
if valid_models:
|
|
230
|
+
examples = valid_models[:VALID_MODEL_EXAMPLE_LIMIT]
|
|
231
|
+
suggested_fix += f"\n\nValid examples: {', '.join(examples)}"
|
|
232
|
+
|
|
233
|
+
super().__init__(message, suggested_fix=suggested_fix, help_url=help_url)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class SetupValidationError(ValidationError):
|
|
237
|
+
"""Raised when setup validation fails."""
|
|
238
|
+
|
|
239
|
+
def __init__(self, validation_type: str, details: str, quick_fixes: list | None = None):
|
|
240
|
+
self.validation_type = validation_type
|
|
241
|
+
self.details = details
|
|
242
|
+
self.quick_fixes = quick_fixes or []
|
|
243
|
+
|
|
244
|
+
suggested_fix = "Run 'tunacode --setup' for guided setup"
|
|
245
|
+
if quick_fixes:
|
|
246
|
+
suggested_fix = f"Try these quick fixes: {', '.join(quick_fixes)}"
|
|
247
|
+
|
|
248
|
+
super().__init__(
|
|
249
|
+
f"{validation_type} validation failed: {details}",
|
|
250
|
+
suggested_fix=suggested_fix,
|
|
251
|
+
valid_examples=["tunacode --setup", "tunacode --help"],
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class TooBroadPatternError(ToolExecutionError):
|
|
256
|
+
"""Raised when a search pattern is too broad and times out."""
|
|
257
|
+
|
|
258
|
+
def __init__(self, pattern: str, timeout_seconds: float):
|
|
259
|
+
self.pattern = pattern
|
|
260
|
+
self.timeout_seconds = timeout_seconds
|
|
261
|
+
super().__init__(
|
|
262
|
+
"grep",
|
|
263
|
+
f"Pattern '{pattern}' is too broad - no matches found within {timeout_seconds}s. "
|
|
264
|
+
"Please use a more specific pattern.",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class GlobalRequestTimeoutError(TunaCodeError):
|
|
269
|
+
"""Raised when a request exceeds the global timeout limit."""
|
|
270
|
+
|
|
271
|
+
def __init__(self, timeout_seconds: float):
|
|
272
|
+
self.timeout_seconds = timeout_seconds
|
|
273
|
+
super().__init__(
|
|
274
|
+
f"Request exceeded global timeout of {timeout_seconds}s. "
|
|
275
|
+
f"The model API may be slow or unresponsive. "
|
|
276
|
+
f"Try increasing settings.global_request_timeout in tunacode.json "
|
|
277
|
+
f"or check model API status."
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class ToolBatchingJSONError(TunaCodeError):
|
|
282
|
+
"""Raised when JSON parsing fails during tool batching after all retries are exhausted."""
|
|
283
|
+
|
|
284
|
+
def __init__(
|
|
285
|
+
self,
|
|
286
|
+
json_content: str,
|
|
287
|
+
retry_count: int,
|
|
288
|
+
original_error: OriginalError = None,
|
|
289
|
+
):
|
|
290
|
+
self.json_content = json_content
|
|
291
|
+
self.retry_count = retry_count
|
|
292
|
+
self.original_error = original_error
|
|
293
|
+
|
|
294
|
+
# Truncate JSON content for display if too long
|
|
295
|
+
truncated_content = json_content[:JSON_TRUNCATION_LIMIT]
|
|
296
|
+
display_content = (
|
|
297
|
+
f"{truncated_content}..." if len(json_content) > JSON_TRUNCATION_LIMIT else json_content
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
super().__init__(
|
|
301
|
+
f"The model is having issues with tool batching. "
|
|
302
|
+
f"JSON parsing failed after {retry_count} retries. "
|
|
303
|
+
f"Invalid JSON: {display_content}"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
class AggregateToolError(TunaCodeError):
|
|
308
|
+
"""Raised when multiple tools fail in parallel execution after retries exhausted."""
|
|
309
|
+
|
|
310
|
+
def __init__(self, failures: list[tuple[str, Exception]]):
|
|
311
|
+
self.failures = failures
|
|
312
|
+
tool_names = [name for name, _ in failures]
|
|
313
|
+
super().__init__(f"Multiple tools failed: {', '.join(tool_names)}")
|