tunacode-cli 0.0.25__tar.gz → 0.0.26__tar.gz

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.

Files changed (98) hide show
  1. {tunacode_cli-0.0.25/src/tunacode_cli.egg-info → tunacode_cli-0.0.26}/PKG-INFO +1 -1
  2. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/pyproject.toml +1 -1
  3. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/configuration/defaults.py +1 -0
  4. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/constants.py +1 -1
  5. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/agents/main.py +19 -2
  6. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/agents/orchestrator.py +16 -0
  7. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/types.py +27 -1
  8. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/output.py +13 -6
  9. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26/src/tunacode_cli.egg-info}/PKG-INFO +1 -1
  10. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode_cli.egg-info/SOURCES.txt +1 -0
  11. tunacode_cli-0.0.26/tests/test_fallback_responses.py +54 -0
  12. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/CLAUDE.md +0 -0
  13. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/LICENSE +0 -0
  14. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/MANIFEST.in +0 -0
  15. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/README.md +0 -0
  16. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/TUNACODE.md +0 -0
  17. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/setup.cfg +0 -0
  18. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/setup.py +0 -0
  19. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/__init__.py +0 -0
  20. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/__init__.py +0 -0
  21. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/commands.py +0 -0
  22. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/main.py +1 -1
  23. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/repl.py +0 -0
  24. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/textual_app.py +0 -0
  25. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/cli/textual_bridge.py +0 -0
  26. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/configuration/__init__.py +0 -0
  27. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/configuration/models.py +0 -0
  28. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/configuration/settings.py +0 -0
  29. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/context.py +0 -0
  30. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/__init__.py +0 -0
  31. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/agents/__init__.py +0 -0
  32. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/agents/planner_schema.py +0 -0
  33. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/agents/readonly.py +0 -0
  34. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/background/__init__.py +0 -0
  35. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/background/manager.py +0 -0
  36. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/llm/__init__.py +0 -0
  37. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/llm/planner.py +0 -0
  38. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/__init__.py +0 -0
  39. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/agent_setup.py +0 -0
  40. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/base.py +0 -0
  41. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/config_setup.py +0 -0
  42. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/coordinator.py +0 -0
  43. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/environment_setup.py +0 -0
  44. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/setup/git_safety_setup.py +0 -0
  45. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/state.py +0 -0
  46. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/core/tool_handler.py +0 -0
  47. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/exceptions.py +0 -0
  48. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/prompts/system.md +0 -0
  49. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/py.typed +0 -0
  50. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/services/__init__.py +0 -0
  51. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/services/mcp.py +0 -0
  52. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/setup.py +0 -0
  53. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/__init__.py +0 -0
  54. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/base.py +0 -0
  55. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/bash.py +0 -0
  56. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/grep.py +0 -0
  57. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/read_file.py +0 -0
  58. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/run_command.py +0 -0
  59. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/update_file.py +0 -0
  60. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/tools/write_file.py +0 -0
  61. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/__init__.py +0 -0
  62. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/completers.py +0 -0
  63. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/console.py +0 -0
  64. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/constants.py +0 -0
  65. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/decorators.py +0 -0
  66. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/input.py +0 -0
  67. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/keybindings.py +0 -0
  68. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/lexers.py +0 -0
  69. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/panels.py +0 -0
  70. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/prompt_manager.py +0 -0
  71. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/tool_ui.py +0 -0
  72. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/ui/validators.py +0 -0
  73. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/__init__.py +0 -0
  74. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/bm25.py +0 -0
  75. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/diff_utils.py +0 -0
  76. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/file_utils.py +0 -0
  77. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/import_cache.py +0 -0
  78. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/ripgrep.py +0 -0
  79. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/system.py +0 -0
  80. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/text_utils.py +0 -0
  81. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode/utils/user_configuration.py +0 -0
  82. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
  83. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
  84. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode_cli.egg-info/requires.txt +0 -0
  85. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/src/tunacode_cli.egg-info/top_level.txt +0 -0
  86. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_agent_initialization.py +0 -0
  87. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_architect_integration.py +0 -0
  88. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_architect_simple.py +0 -0
  89. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_background_manager.py +0 -0
  90. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_config_setup_async.py +0 -0
  91. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_fast_glob_search.py +0 -0
  92. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_file_reference_expansion.py +0 -0
  93. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_json_tool_parsing.py +0 -0
  94. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_orchestrator_file_references.py +0 -0
  95. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_orchestrator_import.py +0 -0
  96. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_orchestrator_planning_visibility.py +0 -0
  97. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_react_thoughts.py +0 -0
  98. {tunacode_cli-0.0.25 → tunacode_cli-0.0.26}/tests/test_update_command.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.25
3
+ Version: 0.0.26
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tunacode-cli"
7
- version = "0.0.25"
7
+ version = "0.0.26"
8
8
  description = "Your agentic CLI developer."
9
9
  keywords = ["cli", "agent", "development", "automation"]
10
10
  readme = "README.md"
@@ -21,6 +21,7 @@ DEFAULT_USER_CONFIG: UserConfig = {
21
21
  "max_iterations": 20,
22
22
  "tool_ignore": [TOOL_READ_FILE],
23
23
  "guide_file": GUIDE_FILE_NAME,
24
+ "fallback_response": True,
24
25
  },
25
26
  "mcpServers": {},
26
27
  }
@@ -7,7 +7,7 @@ Centralizes all magic strings, UI text, error messages, and application constant
7
7
 
8
8
  # Application info
9
9
  APP_NAME = "TunaCode"
10
- APP_VERSION = "0.0.25"
10
+ APP_VERSION = "0.0.26"
11
11
 
12
12
  # File patterns
13
13
  GUIDE_FILE_PATTERN = "{name}.md"
@@ -18,8 +18,8 @@ from tunacode.tools.read_file import read_file
18
18
  from tunacode.tools.run_command import run_command
19
19
  from tunacode.tools.update_file import update_file
20
20
  from tunacode.tools.write_file import write_file
21
- from tunacode.types import (AgentRun, ErrorMessage, ModelName, PydanticAgent, ToolCallback,
22
- ToolCallId, ToolName)
21
+ from tunacode.types import (AgentRun, ErrorMessage, FallbackResponse, ModelName, PydanticAgent,
22
+ ResponseState, SimpleResult, ToolCallback, ToolCallId, ToolName)
23
23
 
24
24
 
25
25
  # Lazy import for Agent and Tool
@@ -343,11 +343,19 @@ async def process_request(
343
343
  mh = state_manager.session.messages.copy()
344
344
  # Get max iterations from config (default: 20)
345
345
  max_iterations = state_manager.session.user_config.get("settings", {}).get("max_iterations", 20)
346
+ fallback_enabled = state_manager.session.user_config.get("settings", {}).get(
347
+ "fallback_response", True
348
+ )
349
+
350
+ response_state = ResponseState()
346
351
 
347
352
  async with agent.iter(message, message_history=mh) as agent_run:
348
353
  i = 0
349
354
  async for node in agent_run:
350
355
  await _process_node(node, tool_callback, state_manager)
356
+ if hasattr(node, "result") and node.result and hasattr(node.result, "output"):
357
+ if node.result.output:
358
+ response_state.has_user_response = True
351
359
  i += 1
352
360
 
353
361
  # Display iteration progress if thoughts are enabled
@@ -362,5 +370,14 @@ async def process_request(
362
370
 
363
371
  await ui.warning(f"⚠️ Reached maximum iterations ({max_iterations})")
364
372
  break
373
+ if not response_state.has_user_response and i >= max_iterations and fallback_enabled:
374
+ patch_tool_messages("Task incomplete", state_manager=state_manager)
375
+ response_state.has_final_synthesis = True
376
+ fallback = FallbackResponse(
377
+ summary="Reached maximum iterations without producing a final response.",
378
+ progress=f"{i}/{max_iterations} iterations completed",
379
+ )
365
380
 
381
+ agent_run.result = SimpleResult(fallback.summary)
382
+ agent_run.response_state = response_state
366
383
  return agent_run
@@ -96,4 +96,20 @@ class OrchestratorAgent:
96
96
 
97
97
  console.print("\n[green]Orchestrator completed all tasks successfully![/green]")
98
98
 
99
+ has_output = any(
100
+ hasattr(r, "result") and r.result and getattr(r.result, "output", None) for r in results
101
+ )
102
+
103
+ if results and not has_output:
104
+ lines = [f"Task {i + 1} completed" for i in range(len(results))]
105
+ summary = "\n".join(lines)
106
+
107
+ class SynthResult:
108
+ def __init__(self, output: str):
109
+ self.output = output
110
+
111
+ synth_run = type("SynthRun", (), {})()
112
+ synth_run.result = SynthResult(summary)
113
+ results.append(synth_run)
114
+
99
115
  return results
@@ -5,7 +5,7 @@ This module contains all type aliases, protocols, and type definitions
5
5
  used throughout the TunaCode codebase.
6
6
  """
7
7
 
8
- from dataclasses import dataclass
8
+ from dataclasses import dataclass, field
9
9
  from pathlib import Path
10
10
  from typing import Any, Awaitable, Callable, Dict, List, Optional, Protocol, Tuple, Union
11
11
 
@@ -134,6 +134,32 @@ AgentRun = Any # pydantic_ai.RunContext or similar
134
134
  AgentConfig = Dict[str, Any]
135
135
  AgentName = str
136
136
 
137
+
138
+ @dataclass
139
+ class ResponseState:
140
+ """Track whether a user visible response was produced."""
141
+
142
+ has_user_response: bool = False
143
+ has_final_synthesis: bool = False
144
+
145
+
146
+ @dataclass
147
+ class FallbackResponse:
148
+ """Structure for synthesized fallback responses."""
149
+
150
+ summary: str
151
+ progress: str = ""
152
+ issues: List[str] = field(default_factory=list)
153
+ next_steps: List[str] = field(default_factory=list)
154
+
155
+
156
+ @dataclass
157
+ class SimpleResult:
158
+ """Simple result container for agent responses."""
159
+
160
+ output: str
161
+
162
+
137
163
  # =============================================================================
138
164
  # Session and State Types
139
165
  # =============================================================================
@@ -17,12 +17,19 @@ console = Console()
17
17
  colors = DotDict(UI_COLORS)
18
18
 
19
19
  BANNER = """[bold cyan]
20
- ████████╗██╗ ██╗███╗ ██╗ █████╗ ██████╗ ██████╗ ██████╗ ███████╗
21
- ╚══██╔══╝██║ ██║████╗ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗██╔════╝
22
- ██║ ██║ ██║██╔██╗ ██║███████║██║ ██║ ██║██║ ██║█████╗
23
- ██║ ██║ ██║██║╚██╗██║██╔══██║██║ ██║ ██║██║ ██║██╔══╝
24
- ██║ ╚██████╔╝██║ ╚████║██║ ██║╚██████╗╚██████╔╝██████╔╝███████╗
25
- ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
20
+ ████████╗██╗ ██╗███╗ ██╗ █████╗
21
+ ╚══██╔══╝██║ ██║████╗ ██║██╔══██╗
22
+ ██║ ██║ ██║██╔██╗ ██║███████║
23
+ ██║ ██║ ██║██║╚██╗██║██╔══██║
24
+ ██║ ╚██████╔╝██║ ╚████║██║ ██║
25
+ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝
26
+
27
+ ██████╗ ██████╗ ██████╗ ███████╗
28
+ ██╔════╝██╔═══██╗██╔══██╗██╔════╝
29
+ ██║ ██║ ██║██║ ██║█████╗
30
+ ██║ ██║ ██║██║ ██║██╔══╝
31
+ ╚██████╗╚██████╔╝██████╔╝███████╗
32
+ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
26
33
  [/bold cyan]
27
34
 
28
35
  ● Caution: This tool can modify your codebase - always use git branches"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.25
3
+ Version: 0.0.26
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -85,6 +85,7 @@ tests/test_architect_integration.py
85
85
  tests/test_architect_simple.py
86
86
  tests/test_background_manager.py
87
87
  tests/test_config_setup_async.py
88
+ tests/test_fallback_responses.py
88
89
  tests/test_fast_glob_search.py
89
90
  tests/test_file_reference_expansion.py
90
91
  tests/test_json_tool_parsing.py
@@ -0,0 +1,54 @@
1
+ import pytest
2
+ from unittest.mock import patch, MagicMock
3
+
4
+ from tunacode.core.state import StateManager
5
+ from tunacode.core.agents import main as agent_main
6
+ from tunacode.core.agents.orchestrator import OrchestratorAgent
7
+
8
+ class DummyNode:
9
+ pass
10
+
11
+ class FakeAgentRun:
12
+ def __init__(self, nodes):
13
+ self._nodes = nodes
14
+ self.result = None
15
+ def __aiter__(self):
16
+ async def gen():
17
+ for n in self._nodes:
18
+ yield n
19
+ return gen()
20
+ async def __aenter__(self):
21
+ return self
22
+ async def __aexit__(self, exc_type, exc, tb):
23
+ pass
24
+
25
+ class FakeAgent:
26
+ def __init__(self, nodes):
27
+ self._nodes = nodes
28
+ def iter(self, message, message_history=None):
29
+ return FakeAgentRun(self._nodes)
30
+
31
+ @pytest.mark.asyncio
32
+ async def test_process_request_generates_fallback():
33
+ state = StateManager()
34
+ state.session.user_config = {
35
+ "settings": {"max_iterations": 3, "fallback_response": True}
36
+ }
37
+ nodes = [DummyNode() for _ in range(5)]
38
+ with patch("tunacode.core.agents.main.get_or_create_agent", return_value=FakeAgent(nodes)):
39
+ res = await agent_main.process_request("model", "test", state)
40
+ assert hasattr(res, "result")
41
+ assert "maximum iterations" in res.result.output.lower()
42
+
43
+ @pytest.mark.asyncio
44
+ async def test_orchestrator_synthesizes_summary():
45
+ state = StateManager()
46
+ orch = OrchestratorAgent(state)
47
+ tasks = [MagicMock(id=1, description="task", mutate=True)]
48
+ fake_run = MagicMock()
49
+ fake_run.result = None
50
+ with patch.object(orch, "plan", return_value=tasks):
51
+ with patch.object(orch, "_run_sub_task", return_value=fake_run):
52
+ results = await orch.run("req")
53
+ assert len(results) == 2
54
+ assert "task 1" in results[-1].result.output.lower()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -11,10 +11,10 @@ import typer
11
11
  from tunacode.cli.repl import repl
12
12
  from tunacode.configuration.settings import ApplicationSettings
13
13
  from tunacode.core.state import StateManager
14
+ from tunacode.exceptions import UserAbortError
14
15
  from tunacode.setup import setup
15
16
  from tunacode.ui import console as ui
16
17
  from tunacode.utils.system import check_for_updates
17
- from tunacode.exceptions import UserAbortError
18
18
 
19
19
  app_settings = ApplicationSettings()
20
20
  app = typer.Typer(help="🐟 TunaCode - Your AI-powered development assistant")