tunacode-cli 0.0.72__py3-none-any.whl → 0.0.75__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/repl.py CHANGED
@@ -3,6 +3,7 @@
3
3
  import asyncio
4
4
  import logging
5
5
  import os
6
+ import re
6
7
  import subprocess
7
8
  from asyncio.exceptions import CancelledError
8
9
  from pathlib import Path
@@ -112,7 +113,7 @@ async def _detect_and_handle_text_plan(state_manager, agent_response, original_r
112
113
  else:
113
114
  response_text = str(agent_response)
114
115
 
115
- if "TUNACODE_TASK_COMPLETE" in response_text:
116
+ if re.search(r"^\s*TUNACODE\s+DONE:\s*", response_text, re.IGNORECASE):
116
117
  await ui.warning(
117
118
  "⚠️ Agent failed to call present_plan tool. Please provide clearer instructions."
118
119
  )
tunacode/constants.py CHANGED
@@ -9,7 +9,7 @@ from enum import Enum
9
9
 
10
10
  # Application info
11
11
  APP_NAME = "TunaCode"
12
- APP_VERSION = "0.0.72"
12
+ APP_VERSION = "0.0.75"
13
13
 
14
14
 
15
15
  # File patterns
@@ -169,18 +169,21 @@ def get_or_create_agent(model: ModelName, state_manager: StateManager) -> Pydant
169
169
 
170
170
  # Add plan mode context if in plan mode
171
171
  if state_manager.is_plan_mode():
172
- # REMOVE all TUNACODE_TASK_COMPLETE instructions from the system prompt
173
- system_prompt = system_prompt.replace(
174
- "TUNACODE_TASK_COMPLETE", "PLAN_MODE_TASK_PLACEHOLDER"
175
- )
172
+ # REMOVE completion instructions from the system prompt in plan mode
173
+ for marker in ("TUNACODE_TASK_COMPLETE", "TUNACODE DONE:"):
174
+ system_prompt = system_prompt.replace(marker, "PLAN_MODE_TASK_PLACEHOLDER")
176
175
  # Remove the completion guidance that conflicts with plan mode
177
176
  lines_to_remove = [
177
+ "When a task is COMPLETE, start your response with: TUNACODE DONE:",
178
+ "4. When a task is COMPLETE, start your response with: TUNACODE DONE:",
178
179
  "When a task is COMPLETE, start your response with: TUNACODE_TASK_COMPLETE",
179
180
  "4. When a task is COMPLETE, start your response with: TUNACODE_TASK_COMPLETE",
180
181
  "**How to signal completion:**",
181
182
  "TUNACODE_TASK_COMPLETE",
183
+ "TUNACODE DONE:",
182
184
  "[Your summary of what was accomplished]",
183
185
  "**IMPORTANT**: Always evaluate if you've completed the task. If yes, use TUNACODE_TASK_COMPLETE.",
186
+ "**IMPORTANT**: Always evaluate if you've completed the task. If yes, use TUNACODE DONE:",
184
187
  "This prevents wasting iterations and API calls.",
185
188
  ]
186
189
  for line in lines_to_remove:
@@ -106,7 +106,7 @@ Attempt: {iteration}
106
106
  Please take one of these specific actions:
107
107
 
108
108
  1. **Search yielded no results?** → Try alternative search terms or broader patterns
109
- 2. **Found what you need?** → Use TUNACODE_TASK_COMPLETE to finalize
109
+ 2. **Found what you need?** → Use TUNACODE DONE: to finalize
110
110
  3. **Encountering a blocker?** → Explain the specific issue preventing progress
111
111
  4. **Need more context?** → Use list_dir or expand your search scope
112
112
 
@@ -5,7 +5,7 @@ from typing import Any, Awaitable, Callable, Optional, Tuple
5
5
 
6
6
  from tunacode.core.logging.logger import get_logger
7
7
  from tunacode.core.state import StateManager
8
- from tunacode.types import UsageTrackerProtocol
8
+ from tunacode.types import AgentState, UsageTrackerProtocol
9
9
  from tunacode.ui.tool_descriptions import get_batch_description, get_tool_description
10
10
 
11
11
  from .response_state import ResponseState
@@ -52,6 +52,12 @@ async def _process_node(
52
52
  has_intention = False
53
53
  has_tool_calls = False
54
54
 
55
+ # Transition to ASSISTANT at the start of node processing
56
+ if response_state and response_state.can_transition_to(AgentState.ASSISTANT):
57
+ response_state.transition_to(AgentState.ASSISTANT)
58
+ if state_manager.session.show_thoughts:
59
+ await ui.muted("STATE → ASSISTANT (reasoning)")
60
+
55
61
  if hasattr(node, "request"):
56
62
  state_manager.session.messages.append(node.request)
57
63
 
@@ -161,8 +167,11 @@ async def _process_node(
161
167
  f"Task completion with pending intentions detected: {found_phrases}"
162
168
  )
163
169
 
164
- # Normal completion
165
- response_state.task_completed = True
170
+ # Normal completion - transition to RESPONSE state and mark completion
171
+ response_state.transition_to(AgentState.RESPONSE)
172
+ if state_manager.session.show_thoughts:
173
+ await ui.muted("STATE → RESPONSE (completion detected)")
174
+ response_state.set_completion_detected(True)
166
175
  response_state.has_user_response = True
167
176
  # Update the part content to remove the marker
168
177
  part.content = cleaned_content
@@ -217,6 +226,14 @@ async def _process_node(
217
226
  node, buffering_callback, state_manager, tool_buffer, response_state
218
227
  )
219
228
 
229
+ # If there were no tools and we processed a model response, transition to RESPONSE
230
+ if response_state and response_state.can_transition_to(AgentState.RESPONSE):
231
+ # Only transition if not already completed (set by completion marker path)
232
+ if not response_state.is_completed():
233
+ response_state.transition_to(AgentState.RESPONSE)
234
+ if state_manager.session.show_thoughts:
235
+ await ui.muted("STATE → RESPONSE (handled output)")
236
+
220
237
  # Determine empty response reason
221
238
  if empty_response_detected:
222
239
  if appears_truncated:
@@ -306,6 +323,11 @@ async def _process_tool_calls(
306
323
  for part in node.model_response.parts:
307
324
  if hasattr(part, "part_kind") and part.part_kind == "tool-call":
308
325
  is_processing_tools = True
326
+ # Transition to TOOL_EXECUTION on first tool call
327
+ if response_state and response_state.can_transition_to(AgentState.TOOL_EXECUTION):
328
+ response_state.transition_to(AgentState.TOOL_EXECUTION)
329
+ if state_manager.session.show_thoughts:
330
+ await ui.muted("STATE → TOOL_EXECUTION (executing tools)")
309
331
  if tool_callback:
310
332
  # Check if this is a read-only tool that can be batched
311
333
  if tool_buffer is not None and part.tool_name in READ_ONLY_TOOLS:
@@ -440,6 +462,16 @@ async def _process_tool_calls(
440
462
  }
441
463
  state_manager.session.tool_calls.append(tool_info)
442
464
 
465
+ # After tools are processed, transition back to RESPONSE
466
+ if (
467
+ is_processing_tools
468
+ and response_state
469
+ and response_state.can_transition_to(AgentState.RESPONSE)
470
+ ):
471
+ response_state.transition_to(AgentState.RESPONSE)
472
+ if state_manager.session.show_thoughts:
473
+ await ui.muted("STATE → RESPONSE (tools finished)")
474
+
443
475
  # Update has_user_response based on presence of actual response content
444
476
  if (
445
477
  response_state
@@ -1,13 +1,116 @@
1
1
  """Response state management for tracking agent processing state."""
2
2
 
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, field
4
+ from typing import Optional
5
+
6
+ from tunacode.types import AgentState
7
+
8
+ from .state_transition import AGENT_TRANSITION_RULES, AgentStateMachine
4
9
 
5
10
 
6
11
  @dataclass
7
12
  class ResponseState:
8
- """Track state across agent response processing."""
13
+ """Enhanced response state using enum-based state machine."""
14
+
15
+ # Internal state machine
16
+ _state_machine: AgentStateMachine = field(
17
+ default_factory=lambda: AgentStateMachine(AgentState.USER_INPUT, AGENT_TRANSITION_RULES)
18
+ )
19
+
20
+ # Backward compatibility boolean flags (derived from enum state)
21
+ _has_user_response: bool = False
22
+ _task_completed: bool = False
23
+ _awaiting_user_guidance: bool = False
24
+ _has_final_synthesis: bool = False
25
+
26
+ def __post_init__(self):
27
+ """Initialize the state machine."""
28
+ if not hasattr(self, "_state_machine"):
29
+ self._state_machine = AgentStateMachine(AgentState.USER_INPUT, AGENT_TRANSITION_RULES)
30
+
31
+ @property
32
+ def current_state(self) -> AgentState:
33
+ """Get the current enum state."""
34
+ return self._state_machine.current_state
35
+
36
+ def transition_to(self, new_state: AgentState) -> None:
37
+ """Transition to a new state."""
38
+ self._state_machine.transition_to(new_state)
39
+
40
+ def can_transition_to(self, target_state: AgentState) -> bool:
41
+ """Check if a transition to the target state is allowed."""
42
+ return self._state_machine.can_transition_to(target_state)
43
+
44
+ # Backward compatibility properties
45
+ @property
46
+ def has_user_response(self) -> bool:
47
+ """Legacy boolean flag for user response detection."""
48
+ return self._has_user_response
49
+
50
+ @has_user_response.setter
51
+ def has_user_response(self, value: bool) -> None:
52
+ """Set the legacy has_user_response flag."""
53
+ self._has_user_response = value
54
+
55
+ @property
56
+ def task_completed(self) -> bool:
57
+ """Legacy boolean flag for task completion (derived from state machine)."""
58
+ # If explicitly set true, honor it; otherwise derive from state machine
59
+ return bool(self._task_completed or self._state_machine.is_completed())
60
+
61
+ @task_completed.setter
62
+ def task_completed(self, value: bool) -> None:
63
+ """Set the legacy task_completed flag and sync with state machine."""
64
+ self._task_completed = bool(value)
65
+ if value:
66
+ # Ensure state reflects completion in RESPONSE
67
+ try:
68
+ if (
69
+ self._state_machine.current_state != AgentState.RESPONSE
70
+ and self._state_machine.can_transition_to(AgentState.RESPONSE)
71
+ ):
72
+ self._state_machine.transition_to(AgentState.RESPONSE)
73
+ except Exception:
74
+ # Best-effort: ignore invalid transition in legacy paths
75
+ pass
76
+ self._state_machine.set_completion_detected(True)
77
+ else:
78
+ self._state_machine.set_completion_detected(False)
79
+
80
+ @property
81
+ def awaiting_user_guidance(self) -> bool:
82
+ """Legacy boolean flag for awaiting user guidance."""
83
+ return self._awaiting_user_guidance
84
+
85
+ @awaiting_user_guidance.setter
86
+ def awaiting_user_guidance(self, value: bool) -> None:
87
+ """Set the legacy awaiting_user_guidance flag."""
88
+ self._awaiting_user_guidance = value
89
+
90
+ @property
91
+ def has_final_synthesis(self) -> bool:
92
+ """Legacy boolean flag for final synthesis."""
93
+ return self._has_final_synthesis
94
+
95
+ @has_final_synthesis.setter
96
+ def has_final_synthesis(self, value: bool) -> None:
97
+ """Set the legacy has_final_synthesis flag."""
98
+ self._has_final_synthesis = value
99
+
100
+ # Enhanced state management methods
101
+ def set_completion_detected(self, detected: bool = True) -> None:
102
+ """Mark that completion has been detected in the RESPONSE state."""
103
+ self._state_machine.set_completion_detected(detected)
104
+
105
+ def is_completed(self) -> bool:
106
+ """Check if the task is completed according to the state machine."""
107
+ return self._state_machine.is_completed()
9
108
 
10
- has_user_response: bool = False
11
- task_completed: bool = False
12
- awaiting_user_guidance: bool = False
13
- has_final_synthesis: bool = False
109
+ def reset_state(self, initial_state: Optional[AgentState] = None) -> None:
110
+ """Reset the state machine to initial state."""
111
+ self._state_machine.reset(initial_state)
112
+ # Reset legacy flags
113
+ self._has_user_response = False
114
+ self._task_completed = False
115
+ self._awaiting_user_guidance = False
116
+ self._has_final_synthesis = False
@@ -0,0 +1,116 @@
1
+ """State transition management for agent response processing."""
2
+
3
+ import threading
4
+ from dataclasses import dataclass
5
+ from enum import Enum
6
+ from typing import TYPE_CHECKING, Dict, Set
7
+
8
+ from tunacode.types import AgentState
9
+
10
+ if TYPE_CHECKING:
11
+ pass
12
+
13
+
14
+ class InvalidStateTransitionError(Exception):
15
+ """Raised when an invalid state transition is attempted."""
16
+
17
+ def __init__(self, from_state: Enum, to_state: Enum, message: str = None):
18
+ self.from_state = from_state
19
+ self.to_state = to_state
20
+ self.message = message or f"Invalid state transition: {from_state.value} → {to_state.value}"
21
+ super().__init__(self.message)
22
+
23
+
24
+ @dataclass
25
+ class StateTransitionRules:
26
+ """Defines valid state transitions for the agent state machine."""
27
+
28
+ # Valid transitions for each state
29
+ valid_transitions: Dict[Enum, Set[Enum]]
30
+
31
+ def is_valid_transition(self, from_state: Enum, to_state: Enum) -> bool:
32
+ """Check if a transition between states is valid."""
33
+ return to_state in self.valid_transitions.get(from_state, set())
34
+
35
+ def get_valid_next_states(self, current_state: Enum) -> Set[Enum]:
36
+ """Get all valid next states from the current state."""
37
+ return self.valid_transitions.get(current_state, set())
38
+
39
+
40
+ class AgentStateMachine:
41
+ """Thread-safe state machine for agent response processing."""
42
+
43
+ def __init__(self, initial_state: "AgentState", rules: StateTransitionRules):
44
+ """
45
+ Initialize the state machine.
46
+
47
+ Args:
48
+ initial_state: The starting state
49
+ rules: Transition rules defining valid state changes
50
+ """
51
+ self._state = initial_state
52
+ self._rules = rules
53
+ self._lock = threading.RLock() # Reentrant lock for thread safety
54
+ self._completion_detected = False
55
+
56
+ @property
57
+ def current_state(self) -> "AgentState":
58
+ """Get the current state."""
59
+ with self._lock:
60
+ return self._state
61
+
62
+ def transition_to(self, new_state: "AgentState") -> None:
63
+ """
64
+ Transition to a new state.
65
+
66
+ Args:
67
+ new_state: The state to transition to
68
+
69
+ Raises:
70
+ InvalidStateTransitionError: If the transition is not valid
71
+ """
72
+ with self._lock:
73
+ if not self._rules.is_valid_transition(self._state, new_state):
74
+ raise InvalidStateTransitionError(
75
+ self._state,
76
+ new_state,
77
+ f"Invalid state transition: {self._state.value} → {new_state.value}",
78
+ )
79
+
80
+ # Handle self-transitions as no-ops
81
+ if self._state == new_state:
82
+ return
83
+
84
+ self._state = new_state
85
+
86
+ def can_transition_to(self, target_state: "AgentState") -> bool:
87
+ """Check if a transition to the target state is allowed."""
88
+ with self._lock:
89
+ return self._rules.is_valid_transition(self._state, target_state)
90
+
91
+ def set_completion_detected(self, detected: bool = True) -> None:
92
+ """Mark that completion has been detected in the RESPONSE state."""
93
+ with self._lock:
94
+ self._completion_detected = detected
95
+
96
+ def is_completed(self) -> bool:
97
+ """Check if the task is completed (only valid in RESPONSE state)."""
98
+ with self._lock:
99
+ return self._state == AgentState.RESPONSE and self._completion_detected
100
+
101
+ def reset(self, initial_state: "AgentState" = None) -> None:
102
+ """Reset the state machine to initial state."""
103
+ with self._lock:
104
+ self._state = initial_state or AgentState.USER_INPUT
105
+ self._completion_detected = False
106
+
107
+
108
+ # Define the transition rules for the agent state machine
109
+ AGENT_TRANSITION_RULES = StateTransitionRules(
110
+ valid_transitions={
111
+ AgentState.USER_INPUT: {AgentState.ASSISTANT},
112
+ AgentState.ASSISTANT: {AgentState.TOOL_EXECUTION, AgentState.RESPONSE},
113
+ AgentState.TOOL_EXECUTION: {AgentState.RESPONSE},
114
+ AgentState.RESPONSE: {AgentState.ASSISTANT}, # Can transition back to continue
115
+ }
116
+ )
@@ -1,5 +1,6 @@
1
1
  """Task completion detection utilities."""
2
2
 
3
+ import re
3
4
  from typing import Tuple
4
5
 
5
6
 
@@ -18,11 +19,14 @@ def check_task_completion(content: str) -> Tuple[bool, str]:
18
19
  if not content:
19
20
  return False, content
20
21
 
21
- lines = content.strip().split("\n")
22
- if lines and lines[0].strip() == "TUNACODE_TASK_COMPLETE":
23
- # Task is complete, return cleaned content
24
- cleaned_lines = lines[1:] if len(lines) > 1 else []
25
- cleaned_content = "\n".join(cleaned_lines).strip()
26
- return True, cleaned_content
22
+ lines = content.split("\n")
23
+
24
+ # New marker: any line starting with "TUNACODE DONE:" (case-insensitive, allow leading whitespace)
25
+ done_pattern = re.compile(r"^\s*TUNACODE\s+DONE:\s*", re.IGNORECASE)
26
+ for idx, line in enumerate(lines):
27
+ if done_pattern.match(line):
28
+ # Remove the marker line and return remaining content
29
+ cleaned = "\n".join(lines[:idx] + lines[idx + 1 :]).strip()
30
+ return True, cleaned
27
31
 
28
32
  return False, content
@@ -97,7 +97,7 @@ async def check_query_satisfaction(
97
97
  state_manager: StateManager,
98
98
  ) -> bool:
99
99
  """Check if the response satisfies the original query."""
100
- return True # Agent uses TUNACODE_TASK_COMPLETE marker
100
+ return True # Completion decided via DONE marker in RESPONSE
101
101
 
102
102
 
103
103
  async def process_request(
@@ -251,7 +251,7 @@ Task: {message[:200]}...
251
251
 
252
252
  You're describing actions but not executing them. You MUST:
253
253
 
254
- 1. If task is COMPLETE: Start response with TUNACODE_TASK_COMPLETE
254
+ 1. If task is COMPLETE: Start response with TUNACODE DONE:
255
255
  2. If task needs work: Execute a tool RIGHT NOW (grep, read_file, bash, etc.)
256
256
  3. If stuck: Explain the specific blocker
257
257
 
@@ -269,7 +269,7 @@ NO MORE DESCRIPTIONS. Take ACTION or mark COMPLETE."""
269
269
  unproductive_iterations = 0
270
270
 
271
271
  # REMOVED: Recursive satisfaction check that caused empty responses
272
- # The agent now decides completion using TUNACODE_TASK_COMPLETE marker
272
+ # The agent now decides completion using a DONE marker
273
273
  # This eliminates recursive agent calls and gives control back to the agent
274
274
 
275
275
  # Store original query for reference
@@ -302,7 +302,7 @@ Progress so far:
302
302
  - Iterations: {i}
303
303
  - Tools used: {tools_used_str}
304
304
 
305
- If the task is complete, I should respond with TUNACODE_TASK_COMPLETE.
305
+ If the task is complete, I should respond with TUNACODE DONE:
306
306
  Otherwise, please provide specific guidance on what to do next."""
307
307
 
308
308
  create_user_message(clarification_content, state_manager)
@@ -10,12 +10,22 @@ CRITICAL BEHAVIOR RULES:
10
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
11
  2. When you say "Let me..." or "I will..." you MUST execute the corresponding tool in THE SAME RESPONSE
12
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
13
+ 4. When a task is COMPLETE, start your response with: TUNACODE DONE:
14
14
  5. If your response is cut off or truncated, you'll be prompted to continue complete your action
15
15
  6. YOU MUST NOT USE ANY EMOJIS, YOU WILL BE PUNISHED FOR EMOJI USE
16
16
 
17
17
  You MUST follow these rules:
18
18
 
19
+ ### Completion Signaling
20
+
21
+ When you have fully completed the user’s task:
22
+
23
+ - Start your response with a single line: `TUNACODE DONE:` followed by a brief outcome summary.
24
+ - Do not add explanations before the DONE line; keep it as the first line.
25
+ - Do NOT mark DONE if you have queued tools in the same response — execute tools first, then mark DONE.
26
+ - Example:
27
+ - `TUNACODE DONE: Implemented enum state machine and updated completion logic`
28
+
19
29
  ###Tool Access Rules###
20
30
 
21
31
  You have 9 powerful tools at your disposal. Understanding their categories is CRITICAL for performance:
tunacode/types.py CHANGED
@@ -209,6 +209,15 @@ class PlanPhase(Enum):
209
209
  REVIEW_DECISION = "review"
210
210
 
211
211
 
212
+ class AgentState(Enum):
213
+ """Agent loop states for enhanced completion detection."""
214
+
215
+ USER_INPUT = "user_input" # Initial: user prompt received
216
+ ASSISTANT = "assistant" # Reasoning/deciding phase
217
+ TOOL_EXECUTION = "tool_execution" # Tool execution phase
218
+ RESPONSE = "response" # Handling results, may complete or loop
219
+
220
+
212
221
  @dataclass
213
222
  class PlanDoc:
214
223
  """Structured plan document with all required sections."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.72
3
+ Version: 0.0.75
4
4
  Summary: Your agentic CLI developer.
5
5
  Project-URL: Homepage, https://tunacode.xyz/
6
6
  Project-URL: Repository, https://github.com/alchemiststudiosDOTai/tunacode
@@ -1,13 +1,13 @@
1
1
  tunacode/__init__.py,sha256=yUul8igNYMfUrHnYfioIGAqvrH8b5BKiO_pt1wVnmd0,119
2
- tunacode/constants.py,sha256=FYWE1jM_GF0w6PQOXalzbHaQ68kxdG-li_5pLy7KNAg,6100
2
+ tunacode/constants.py,sha256=V6bVzLomBc0eSTlVWneBKUo1SYzfKh1pQONyhHANPu0,6100
3
3
  tunacode/context.py,sha256=YtfRjUiqsSkk2k9Nn_pjb_m-AXyh6XcOBOJWtFI0wVw,2405
4
4
  tunacode/exceptions.py,sha256=m80njR-LqBXhFAEOPqCE7N2QPU4Fkjlf_f6CWKO0_Is,8479
5
5
  tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  tunacode/setup.py,sha256=F1E4zHVnbByu_Uo6AhCJ-W-lIGF_gV6kB84HLAGLmVY,2103
7
- tunacode/types.py,sha256=Q3PeHB01qeaKteGDQf8Byx4q1XLSXVnNDG6D-WjWsBk,10157
7
+ tunacode/types.py,sha256=xNpDRjIRYg4qGNbl3EG8B13CWAWBoob9ekVm8_6dvnc,10496
8
8
  tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
9
9
  tunacode/cli/main.py,sha256=DEXS8ODPcsaT1MFBGALX5X7eoohMZDSg6sSW3kOgJxk,3136
10
- tunacode/cli/repl.py,sha256=jhKMAff4kxt5f2ONacPao2wgcZvNr2BRBZdITh5yDro,22480
10
+ tunacode/cli/repl.py,sha256=DHI0X8yI9tYvp1PUSR31nTIsp6RF8Aq-WDVHULYPHVA,22516
11
11
  tunacode/cli/commands/__init__.py,sha256=J7MZofTaSgspAKP64OavPukj4l53qvkv_-sCfYEUi10,1794
12
12
  tunacode/cli/commands/base.py,sha256=Ge_lNQA-GDfcb1Ap1oznCH3UrifBiHH3bA9DNL-tCDw,2519
13
13
  tunacode/cli/commands/registry.py,sha256=oAppbaOb-2blVo7Akthu6dbR9UFvXom6wf8m52qftpU,14962
@@ -43,17 +43,18 @@ tunacode/core/code_index.py,sha256=2qxEn2eTIegV4F_gLeZO5lAOv8mkf4Y_t21whZ9F2Fk,1
43
43
  tunacode/core/state.py,sha256=aksE0mM2xG-1CkLmpi8cu1n1SOMfqpMuqMBciEVShf0,7893
44
44
  tunacode/core/tool_handler.py,sha256=42yUfnq5jgk-0LK93JoJgtsXfVDTf-7hNXyKEfH2FM0,3626
45
45
  tunacode/core/agents/__init__.py,sha256=UUJiPYb91arwziSpjd7vIk7XNGA_4HQbsOIbskSqevA,149
46
- tunacode/core/agents/main.py,sha256=8K5f_-gXm3VyAMM8FqH2ucZBjKnVJ8kcqEpov-5qk-c,18244
46
+ tunacode/core/agents/main.py,sha256=50V1FMfJ6lac6XqWqH5KLY_12RDiY-FFgieXbf-tQKM,18217
47
47
  tunacode/core/agents/utils.py,sha256=ja6Dwq3AVX6QTddmG2uY5ENxFxr5uzc4TS9OjommXp0,14535
48
48
  tunacode/core/agents/agent_components/__init__.py,sha256=CL4XH47T6v_iYy7xCPYjyiEFNOFnkcKwbTuKw6IjKTs,1474
49
- tunacode/core/agents/agent_components/agent_config.py,sha256=cuwSR2xLZuTlds3nNh6r95PnsoCh8XAj_GSymPQvrrk,12757
50
- tunacode/core/agents/agent_components/agent_helpers.py,sha256=-jeihh0oWZ4VZ81GUhpYFQ2v8EGw9j9WU81swUjTAvk,8276
49
+ tunacode/core/agents/agent_components/agent_config.py,sha256=rVoFxmtu8Ly6-UAqTzvyv1NgPYTG5ZuYzJf5Qgo4384,13096
50
+ tunacode/core/agents/agent_components/agent_helpers.py,sha256=FFX-zXDhNoXpzMVe2iznBpNzNtk7OJ2lHf44cfZhTk8,8268
51
51
  tunacode/core/agents/agent_components/json_tool_parser.py,sha256=HuyNT0rs-ppx_gLAI2e0XMVGbR_F0WXZfP3sx38VoMg,3447
52
52
  tunacode/core/agents/agent_components/message_handler.py,sha256=KJGOtb9VhumgZpxxwO45HrKLhU9_MwuoWRsSQwJviNU,3704
53
- tunacode/core/agents/agent_components/node_processor.py,sha256=BAVbXy17sfW3i4LCTdJ9_MSNc7j6qz1bP3_6IhprIW4,20912
54
- tunacode/core/agents/agent_components/response_state.py,sha256=_C2loLeyZHMFHwjGny4h0dI02UoFJcJAVaabkh9H9JQ,343
53
+ tunacode/core/agents/agent_components/node_processor.py,sha256=n_m3FYH_3pQ2AH-OJvoZ1J5mFzAYc_U2TdZph5GAHvQ,22753
54
+ tunacode/core/agents/agent_components/response_state.py,sha256=qnjRSQCYZzac04CcVc4gTvW8epxl4w-Vz0kPjsvM_Qg,4482
55
55
  tunacode/core/agents/agent_components/result_wrapper.py,sha256=9CFK0wpsfZx2WT4PBHfkSv22GxL1gAQuUYVMlmYtCJU,1761
56
- tunacode/core/agents/agent_components/task_completion.py,sha256=BSnjNEFbxlzgzcXdjdTVGeCr1RpCiAaEp_D7f5FXa5Q,819
56
+ tunacode/core/agents/agent_components/state_transition.py,sha256=uyvLJriexosBDQIrxbVDLR_luvXAMG6tnDsX10mbZcI,4077
57
+ tunacode/core/agents/agent_components/task_completion.py,sha256=2mgrnNBTuGHYEPB2MS7ndsG-scqN5Qf1A85mxWZikJE,975
57
58
  tunacode/core/agents/agent_components/tool_buffer.py,sha256=09FNtC6zTjiJOL_2CY0b7KDgwdNayGPV6jbENKH6Unc,766
58
59
  tunacode/core/agents/agent_components/tool_executor.py,sha256=LlzDwgSLLawwPZQqJ4vfLf-16nhwIiuN8zm8iCeBf1Y,1849
59
60
  tunacode/core/agents/agent_components/truncation_checker.py,sha256=XbJ3wwtdC4NhgIMIvFR0z_cfNnYMkiYAZo9zGDBPU8Y,2685
@@ -76,7 +77,7 @@ tunacode/core/setup/template_setup.py,sha256=0lDGhNVCvGN7ykqHnl3pj4CONH3I2PvMzkm
76
77
  tunacode/core/token_usage/api_response_parser.py,sha256=plLltHg4zGVzxjv3MFj45bbd-NOJeT_v3P0Ki4zlvn4,1831
77
78
  tunacode/core/token_usage/cost_calculator.py,sha256=RjO-O0JENBuGOrWP7QgBZlZxeXC-PAIr8tj_9p_BxOU,2058
78
79
  tunacode/core/token_usage/usage_tracker.py,sha256=YUCnF-712nLrbtEvFrsC-VZuYjKUCz3hf-_do6GKSDA,6016
79
- tunacode/prompts/system.md,sha256=DosWJgUDkE33mSQoLNz_R5S2CZ_s06yZ5O0lpC1pZtY,10788
80
+ tunacode/prompts/system.md,sha256=UxuEwL9LDZKvnIbV7s_q3JQ852Vsvt9pdqqdoPOZRyM,11226
80
81
  tunacode/prompts/system.md.bak,sha256=q0gbk_-pvQlNtZBonRo4gNILkKStqNxgDN0ZEwzC3E4,17541
81
82
  tunacode/services/__init__.py,sha256=w_E8QK6RnvKSvU866eDe8BCRV26rAm4d3R-Yg06OWCU,19
82
83
  tunacode/services/mcp.py,sha256=quO13skECUGt-4QE2NkWk6_8qhmZ5qjgibvw8tUOt-4,3761
@@ -150,8 +151,8 @@ tunacode/utils/system.py,sha256=J8KqJ4ZqQrNSnM5rrJxPeMk9z2xQQp6dWtI1SKBY1-0,1112
150
151
  tunacode/utils/text_utils.py,sha256=HAwlT4QMy41hr53cDbbNeNo05MI461TpI9b_xdIv8EY,7288
151
152
  tunacode/utils/token_counter.py,sha256=dmFuqVz4ywGFdLfAi5Mg9bAGf8v87Ek-mHU-R3fsYjI,2711
152
153
  tunacode/utils/user_configuration.py,sha256=OA-L0BgWNbf9sWpc8lyivgLscwJdpdI8TAYbe0wRs1s,4836
153
- tunacode_cli-0.0.72.dist-info/METADATA,sha256=Rc0CTBz0g1gfPGKXfs5kMSaq6Zq5eDlrTQCOHxN0xu8,6898
154
- tunacode_cli-0.0.72.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
155
- tunacode_cli-0.0.72.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
156
- tunacode_cli-0.0.72.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
157
- tunacode_cli-0.0.72.dist-info/RECORD,,
154
+ tunacode_cli-0.0.75.dist-info/METADATA,sha256=A9xG7bSy8cowstguwUJorSZi6gMEXdrHUc2v9fLQk-o,6898
155
+ tunacode_cli-0.0.75.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
156
+ tunacode_cli-0.0.75.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
157
+ tunacode_cli-0.0.75.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
158
+ tunacode_cli-0.0.75.dist-info/RECORD,,