Skip to content

Commit c990c99

Browse files
committed
Raise test coverage to 100%.
1 parent 2c4ed9c commit c990c99

16 files changed

Lines changed: 3097 additions & 4 deletions

python_agent_harness/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def make_session(
8181
def cmd_run(args: argparse.Namespace) -> int:
8282
from .tui import Tui
8383

84-
project_dir = args.project or os.getcwd()
84+
project_dir = getattr(args, "project", None) or os.getcwd()
8585
session = make_session(
8686
project_dir, config_path=args.config,
8787
stream=False if getattr(args, "no_stream", False) else None,

tests/test_agent.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,63 @@ def chat(self, messages, **k):
13841384
self.assertIsNone(loop1.run())
13851385
self.assertEqual(deltas, [])
13861386

1387+
def test_compact_no_user_request_returns_false(self):
1388+
"""Compaction needs a real (non-nudge) user request to resume
1389+
with; without one it must fail cleanly."""
1390+
session = RecordingSession()
1391+
loop = AgentLoop(session, messages=[Message(role="assistant", content="hi")])
1392+
self.assertFalse(loop.compact())
1393+
1394+
def test_compact_empty_summary_returns_false(self):
1395+
"""A compaction response with no text must not replace the
1396+
conversation (fail cleanly, reset the compacting flag)."""
1397+
session = RecordingSession()
1398+
1399+
def empty_chat_sync(messages, system=None, temperature=None,
1400+
max_tokens=None, reasoning_effort=None):
1401+
return Message(role="assistant", content=""), Usage()
1402+
1403+
session.client.chat_sync = empty_chat_sync
1404+
loop = AgentLoop(session, messages=[Message(role="user", content="do it")])
1405+
self.assertFalse(loop.compact())
1406+
self.assertFalse(session.compacting)
1407+
1408+
def test_compact_client_error_returns_false(self):
1409+
"""A failing compaction request is non-fatal: it is logged and
1410+
the loop continues without replacing the history."""
1411+
session = RecordingSession()
1412+
1413+
def boom_chat_sync(messages, system=None, temperature=None,
1414+
max_tokens=None, reasoning_effort=None):
1415+
raise RuntimeError("compaction API down")
1416+
1417+
session.client.chat_sync = boom_chat_sync
1418+
loop = AgentLoop(session, messages=[Message(role="user", content="do it")])
1419+
self.assertFalse(loop.compact())
1420+
self.assertFalse(session.compacting)
1421+
1422+
def test_error_state_beats_terminal_response(self):
1423+
"""If the loop carries an error state, the error text wins over
1424+
a terminal response (defensive path for the post-supervision
1425+
error check)."""
1426+
session = RecordingSession()
1427+
session.tools_enabled = False
1428+
session.client.script = ["hello"]
1429+
loop = AgentLoop(session, messages=[Message(role="user", content="hi")])
1430+
loop.error = "boom"
1431+
self.assertEqual(loop.run(), "Error: boom")
1432+
1433+
def test_zero_budget_subagent_returns_none(self):
1434+
"""A sub-agent loop with max_rounds=0 and no assistant text has
1435+
nothing to surface: run() returns None."""
1436+
session = RecordingSession()
1437+
loop = AgentLoop(
1438+
session,
1439+
messages=[Message(role="user", content="hi")],
1440+
top_level=False, max_rounds=0,
1441+
)
1442+
self.assertIsNone(loop.run())
1443+
13871444

13881445
class TestParallelToolRounds(unittest.TestCase):
13891446
def test_cancel_before_round_skips_all_tools(self):

0 commit comments

Comments
 (0)