tunacode-cli 0.0.29__py3-none-any.whl → 0.0.31__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.

@@ -1,65 +0,0 @@
1
- """Read-only agent implementation for non-mutating operations."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import TYPE_CHECKING
6
-
7
- from ...tools.grep import grep
8
- from ...tools.read_file import read_file
9
- from ...types import AgentRun, ModelName, ResponseState
10
- from ..state import StateManager
11
-
12
- if TYPE_CHECKING:
13
- from ...types import PydanticAgent
14
-
15
-
16
- class ReadOnlyAgent:
17
- """Agent configured with read-only tools for analysis tasks."""
18
-
19
- def __init__(self, model: ModelName, state_manager: StateManager):
20
- self.model = model
21
- self.state_manager = state_manager
22
- self._agent: PydanticAgent | None = None
23
-
24
- def _get_agent(self) -> PydanticAgent:
25
- """Lazily create the agent with read-only tools."""
26
- if self._agent is None:
27
- from .main import get_agent_tool
28
-
29
- Agent, Tool = get_agent_tool()
30
-
31
- # Create agent with only read-only tools
32
- self._agent = Agent(
33
- model=self.model,
34
- system_prompt="You are a read-only assistant. You can analyze and read files but cannot modify them.",
35
- tools=[
36
- Tool(read_file),
37
- Tool(grep),
38
- ],
39
- )
40
- return self._agent
41
-
42
- async def process_request(self, request: str) -> AgentRun:
43
- """Process a request using only read-only tools."""
44
- agent = self._get_agent()
45
- response_state = ResponseState()
46
-
47
- # Use iter() like main.py does to get the full run context
48
- async with agent.iter(request) as agent_run:
49
- async for node in agent_run:
50
- # Check if this node produced user-visible output
51
- if hasattr(node, "result") and node.result and hasattr(node.result, "output"):
52
- if node.result.output:
53
- response_state.has_user_response = True
54
-
55
- # Wrap the agent run to include response_state
56
- class AgentRunWithState:
57
- def __init__(self, wrapped_run):
58
- self._wrapped = wrapped_run
59
- self.response_state = response_state
60
-
61
- def __getattr__(self, name):
62
- # Delegate all other attributes to the wrapped object
63
- return getattr(self._wrapped, name)
64
-
65
- return AgentRunWithState(agent_run)
@@ -1,62 +0,0 @@
1
- from typing import List
2
-
3
- from ...types import ModelName
4
- from ..agents.planner_schema import Task
5
- from ..state import StateManager
6
-
7
- _SYSTEM = """You are a senior software project planner.
8
-
9
- Your job is to break down a USER_REQUEST into a logical sequence of tasks.
10
-
11
- Guidelines:
12
- 1. Use the FEWEST tasks possible - combine related operations
13
- 2. Order tasks logically - reads before writes, understand before modify
14
- 3. Mark read-only tasks (reading files, searching, analyzing) as mutate: false
15
- 4. Mark modifying tasks (writing, updating, creating files) as mutate: true
16
- 5. Write clear, actionable descriptions
17
-
18
- Each task MUST have:
19
- - id: Sequential number starting from 1
20
- - description: Clear description of what needs to be done
21
- - mutate: true if the task modifies files/code, false if it only reads/analyzes
22
-
23
- Return ONLY a valid JSON array of tasks, no other text.
24
- Example:
25
- [
26
- {"id": 1, "description": "Read the main.py file to understand the structure", "mutate": false},
27
- {"id": 2, "description": "Update the function to handle edge cases", "mutate": true}
28
- ]"""
29
-
30
-
31
- async def make_plan(request: str, model: ModelName, state_manager: StateManager) -> List[Task]:
32
- """Generate an execution plan from a user request using TunaCode's LLM infrastructure."""
33
- # Lazy import to avoid circular dependencies
34
- from rich.console import Console
35
-
36
- from ..agents.main import get_agent_tool
37
-
38
- console = Console()
39
- Agent, _ = get_agent_tool()
40
-
41
- # Show planning is starting
42
- console.print("\n[dim][Planning] Breaking down request into tasks...[/dim]")
43
-
44
- # Create a simple planning agent
45
- planner = Agent(
46
- model=model,
47
- system_prompt=_SYSTEM,
48
- result_type=List[Task],
49
- )
50
-
51
- # Get the plan from the agent
52
- result = await planner.run(request)
53
- tasks = result.data
54
-
55
- # Display the plan
56
- console.print(f"[dim][Planning] Generated {len(tasks)} tasks:[/dim]")
57
- for task in tasks:
58
- task_type = "WRITE" if task.mutate else "READ"
59
- console.print(f"[dim] Task {task.id}: {task_type} - {task.description}[/dim]")
60
- console.print("")
61
-
62
- return tasks