core/agent+tools+cli: number todos by listing order, not the internal id

This commit is contained in:
2026-10-16 18:52:36 +08:00
parent ac33e92d33
commit 2eb99a079d
9 changed files with 192 additions and 79 deletions
+12 -12
View File
@@ -174,28 +174,28 @@ async def test_pretty_todo_push(capsys: pytest.CaptureFixture[str]) -> None:
)
)
result = (
"pushed group (depth=1) items=[a1]\n"
"pushed group (depth=1) items=[T1]\n"
"(LIFO of groups: depth=1; TOP group = current breakdown level)\n"
"group d=0 TOP:\n"
" [ ] a1: T1"
" [ ] 1. T1"
)
await render_events(_aiter([call, _result(result)]))
out = capsys.readouterr().out
assert "* Todo Push:" in out
assert " [ ] a1: T1" in out
assert " [ ] 1. T1" in out
assert "[tool]" not in out
async def test_pretty_todo_batch_merges_to_one_stack(capsys: pytest.CaptureFixture[str]) -> None:
"""A batch of todo calls: one summary line, then the last result's stack."""
stack = "(LIFO of groups: depth=1; TOP group = current breakdown level)\ngroup d=0 TOP:\n [ ] a1: T1"
stack = "(LIFO of groups: depth=1; TOP group = current breakdown level)\ngroup d=0 TOP:\n [ ] 1. T1"
await render_events(
_aiter(
[
_pretty_call("todo_push", '{"titles": ["T1"]}'),
_pretty_call("todo_update", '{"item_id": "a1", "status": "done"}'),
_result(f"pushed group (depth=1) items=[a1]\n{stack}"),
_result(f"updated a1 → done: T1\n{stack}"),
_pretty_call("todo_update", '{"number": 1, "status": "done"}'),
_result(f"pushed group (depth=1) items=[T1]\n{stack}"),
_result(f"updated 1 → done: T1\n{stack}"),
]
)
)
@@ -206,14 +206,14 @@ async def test_pretty_todo_batch_merges_to_one_stack(capsys: pytest.CaptureFixtu
# Only the last result is printed, so the stack renders once.
assert out.count("group d=0 TOP:") == 1
assert "pushed group" not in out
assert "updated a1 → done: T1" in out
assert "updated 1 → done: T1" in out
async def test_pretty_todo_batch_mixed_with_other_tool_stays_per_call(
capsys: pytest.CaptureFixture[str],
) -> None:
"""A batch holding a non-todo call keeps one line (and stack) per todo call."""
stack = "group d=0 TOP:\n [ ] a1: T1"
stack = "group d=0 TOP:\n [ ] 1. T1"
await render_events(
_aiter(
[
@@ -867,13 +867,13 @@ async def test_pretty_vcs_kind_branch_and_diff(capsys: pytest.CaptureFixture[str
async def test_pretty_todo_list_pop_and_clear(capsys: pytest.CaptureFixture[str]) -> None:
stack = " [ ] a1: T1\n [x] a2: T2"
stack = " [ ] 1. T1\n [x] 2. T2"
await render_events(_aiter([_pretty_call("todo_list", "{}"), _result(stack)]))
out = capsys.readouterr().out
assert "* Todo List:" in out
assert " [ ] a1: T1" in out
assert " [ ] 1. T1" in out
await render_events(_aiter([_pretty_call("todo_pop", "{}"), _result(f"popped TOP group (a1:T1)\n{stack}")]))
await render_events(_aiter([_pretty_call("todo_pop", "{}"), _result(f"popped TOP group (T1)\n{stack}")]))
out = capsys.readouterr().out
assert "* Todo Pop:" in out
+3 -3
View File
@@ -194,9 +194,9 @@ def test_complete_slash_args_from_registry(tmp_path: object) -> None:
state.todo_stack = TodoStack()
_ = state.todo_stack.push_group(["alpha", "beta"])
ids = complete_slash_args(state, "/todos", "t", prior_args=["done"])
assert "t1" in ids
assert "t2" in ids
numbers = complete_slash_args(state, "/todos", "", prior_args=["done"])
assert numbers == ["1", "2"]
assert complete_slash_args(state, "/todos", "2", prior_args=["done"]) == ["2"]
state.remember_session_ids([3, 12, 40])
assert complete_slash_args(state, "/resume", "1") == ["12"]
+23
View File
@@ -757,3 +757,26 @@ async def test_btw_read_notice_states_read_only_scope(
assert "read-only" in notice.body
assert "not saved" in notice.body
assert "[notice] aside: read tools" in capsys.readouterr().out
async def test_todos_update_takes_a_listing_number(state: ReplState, capsys: pytest.CaptureFixture[str]) -> None:
assert await handle_slash(state, "/todos push first; second") is True
out = capsys.readouterr().out
assert "pushed group depth=1 items=[first, second]" in out
assert " [ ] 1. first" in out
assert " [ ] 2. second" in out
assert "t1" not in out
assert await handle_slash(state, "/todos done 2") is True
out = capsys.readouterr().out
assert "updated 2 → done" in out
assert " [x] 2. second" in out
# The stored id is not an address: only listing numbers are.
assert await handle_slash(state, "/todos done t1") is True
assert "takes an item number from the list" in capsys.readouterr().out
assert await handle_slash(state, "/todos done 7") is True
assert "no todo item 7" in capsys.readouterr().out
assert await handle_slash(state, "/todos pop") is True
assert "popped TOP group (first, second)" in capsys.readouterr().out