mindcode 0.5.1__tar.gz → 0.5.2__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.
- {mindcode-0.5.1 → mindcode-0.5.2}/PKG-INFO +1 -1
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/_version.py +1 -1
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/render.py +13 -4
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/PKG-INFO +1 -1
- {mindcode-0.5.1 → mindcode-0.5.2}/pyproject.toml +1 -1
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_render_exec.py +62 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/README.md +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/__main__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/acp_agent/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/acp_agent/__main__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/acp_agent/agent.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/approval.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/base.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/mini_bfcl.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/mini_gaia.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/mini_terminal.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/swe_bench.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/adapters/terminal_bench.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/fake_tools.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/jsonutil.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/paths.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/predictions.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/report.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/runner.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/schema.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/base.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/composite.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/exact.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/json_call.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/swe.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/terminal.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/scorers/terminal_bench.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/trace.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/bench/workspace.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/_shared.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/bench.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/chat.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/config_cmd.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/remote.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/shell.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/status.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/task.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/commands/terminal.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/completion.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/input_pipeline.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/menu.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/repl.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/slash.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/startup.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/cli/shell/tui.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/config.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/mcp.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/policy.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/remote.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/runtime.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/skills.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/subagents.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/tasking.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/terminal/__init__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/terminal/__main__.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode/terminal_core.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/SOURCES.txt +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/dependency_links.txt +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/entry_points.txt +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/requires.txt +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/mindcode.egg-info/top_level.txt +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/setup.cfg +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_acp_agent.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_approval.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_bench.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_cli_commands.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_config.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_diff_capture.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_exec_command_guard.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_external_file_approval.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_policy_choice.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_policy_timeout.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_provider_retry_defaults.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_reasoner_compat.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_remote.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_channels.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_completion.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_interrupt.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_session.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_slash_priority.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_shell_tui.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_skills_mcp.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_slash_resume.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_subagents.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_system_prompt.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_task_resume.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_tasking.py +0 -0
- {mindcode-0.5.1 → mindcode-0.5.2}/tests/test_terminal.py +0 -0
|
@@ -159,10 +159,11 @@ class RichRenderer:
|
|
|
159
159
|
if _command_is_running(ok, result):
|
|
160
160
|
session_id = result.get("session_id", "")
|
|
161
161
|
preview = _first_line(_command_output(result))
|
|
162
|
-
detail = f"running · {session_id}"
|
|
162
|
+
detail = f"{'running' if ok else 'timeout'} · {session_id}"
|
|
163
163
|
if preview:
|
|
164
164
|
detail += f" · {preview}"
|
|
165
|
-
|
|
165
|
+
marker = "[yellow]…[/yellow]" if ok else "[red]✗[/red]"
|
|
166
|
+
self.console.print(f" {marker} {detail}")
|
|
166
167
|
return
|
|
167
168
|
exit_code, timed_out, succeeded, reason = _command_status(
|
|
168
169
|
name, ok, result, error
|
|
@@ -298,6 +299,12 @@ class RichRenderer:
|
|
|
298
299
|
session_id = result.get("session_id", "")
|
|
299
300
|
if isinstance(session_id, str) and self._tui_action_tool is not None:
|
|
300
301
|
self._tui_session_tools[session_id] = self._tui_action_tool
|
|
302
|
+
if not ok:
|
|
303
|
+
preview = _first_line(_command_output(result))
|
|
304
|
+
detail = f"timeout · {session_id}"
|
|
305
|
+
if preview:
|
|
306
|
+
detail += f" · {preview}"
|
|
307
|
+
self._finish_tui_tool(False, detail)
|
|
301
308
|
return
|
|
302
309
|
exit_code, timed_out, succeeded, reason = _command_status(
|
|
303
310
|
name, ok, result, error
|
|
@@ -462,11 +469,13 @@ def _command_status(
|
|
|
462
469
|
|
|
463
470
|
|
|
464
471
|
def _command_is_running(ok: bool, result: Any) -> bool:
|
|
472
|
+
del ok
|
|
465
473
|
return (
|
|
466
|
-
|
|
467
|
-
and isinstance(result, dict)
|
|
474
|
+
isinstance(result, dict)
|
|
468
475
|
and result.get("ok") is True
|
|
469
476
|
and result.get("state") == "running"
|
|
477
|
+
and isinstance(result.get("session_id"), str)
|
|
478
|
+
and bool(result.get("session_id"))
|
|
470
479
|
)
|
|
471
480
|
|
|
472
481
|
|
|
@@ -8,6 +8,7 @@ import unittest
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
|
|
10
10
|
from mindagent.core import AgentState, AgentEvent, EventType
|
|
11
|
+
from mindcode.cli.shell.tui import Transcript
|
|
11
12
|
from mindcode.render import RichRenderer
|
|
12
13
|
|
|
13
14
|
|
|
@@ -163,6 +164,67 @@ class ExecRenderTest(unittest.TestCase):
|
|
|
163
164
|
|
|
164
165
|
self.assertIn("running · s_live · epoch 2", out)
|
|
165
166
|
|
|
167
|
+
def test_action_timeout_renders_recoverable_session(self) -> None:
|
|
168
|
+
out = self._render(
|
|
169
|
+
_make_observation(
|
|
170
|
+
ok=False,
|
|
171
|
+
error="Action exceeded timeout",
|
|
172
|
+
result={
|
|
173
|
+
"ok": True,
|
|
174
|
+
"state": "running",
|
|
175
|
+
"session_id": "s_recoverable",
|
|
176
|
+
"pid": 123,
|
|
177
|
+
"exit_code": None,
|
|
178
|
+
"output": {"text": "still working\n"},
|
|
179
|
+
"error": None,
|
|
180
|
+
"meta": {},
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
self.assertIn("timeout · s_recoverable · still working", out)
|
|
186
|
+
|
|
187
|
+
def test_tui_action_timeout_card_shows_recoverable_session_id(self) -> None:
|
|
188
|
+
async def render() -> Transcript:
|
|
189
|
+
transcript = Transcript()
|
|
190
|
+
renderer = RichRenderer(console=Console(file=io.StringIO()))
|
|
191
|
+
renderer.attach_transcript(transcript)
|
|
192
|
+
await renderer(
|
|
193
|
+
_make_event(
|
|
194
|
+
"exec_command",
|
|
195
|
+
{"command": "python train.py"},
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
await renderer(
|
|
199
|
+
_make_observation(
|
|
200
|
+
ok=False,
|
|
201
|
+
error="Action exceeded timeout",
|
|
202
|
+
result={
|
|
203
|
+
"ok": True,
|
|
204
|
+
"state": "running",
|
|
205
|
+
"session_id": "s_recoverable",
|
|
206
|
+
"pid": 123,
|
|
207
|
+
"exit_code": None,
|
|
208
|
+
"output": {"text": "still working\n"},
|
|
209
|
+
"error": None,
|
|
210
|
+
"meta": {},
|
|
211
|
+
},
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
return transcript
|
|
215
|
+
|
|
216
|
+
import asyncio
|
|
217
|
+
|
|
218
|
+
transcript = asyncio.run(render())
|
|
219
|
+
tool_entries = [entry for entry in transcript.entries if entry.role == "tool"]
|
|
220
|
+
|
|
221
|
+
self.assertEqual(len(tool_entries), 1)
|
|
222
|
+
self.assertEqual(tool_entries[0].status, "error")
|
|
223
|
+
self.assertEqual(
|
|
224
|
+
tool_entries[0].content,
|
|
225
|
+
"timeout · s_recoverable · still working",
|
|
226
|
+
)
|
|
227
|
+
|
|
166
228
|
def test_structured_runtime_error_uses_error_message(self) -> None:
|
|
167
229
|
out = self._render(
|
|
168
230
|
_make_observation(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|