Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/bub/builtin/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ async def tape_search(param: SearchInput, *, context: ToolContext) -> str:
if "[tape.search]" in entry_str:
continue
lines.append(entry_str)
return f"[tape.search]: {len(entries)} matches" + "".join(f"\n{line}" for line in lines)
return f"[tape.search]: {len(lines)} matches ({len(entries) - len(lines)} filtered)" + "".join(
f"\n{line}" for line in lines
)


@tool(context=True, name="tape.reset")
Expand Down
55 changes: 55 additions & 0 deletions tests/test_tape_search_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from __future__ import annotations

from dataclasses import dataclass

import pytest
from republic import ToolContext

import bub.builtin.tools as builtin_tools
from bub.builtin.tools import tape_search


@dataclass(frozen=True)
class _FakeEntry:
date: str
payload: object


class _FakeTapes:
def __init__(self, entries: list[_FakeEntry]) -> None:
self._entries = entries
self._store = object()

async def search(self, _query: object) -> list[_FakeEntry]:
return list(self._entries)


class _FakeAgent:
def __init__(self, entries: list[_FakeEntry]) -> None:
self.tapes = _FakeTapes(entries)


@pytest.mark.asyncio
async def test_tape_search_reports_shown_matches_and_filtered_count(monkeypatch) -> None:
entries = [
_FakeEntry(date="2026-01-01T00:00:00Z", payload={"content": "ok"}),
_FakeEntry(date="2026-01-01T00:00:01Z", payload={"content": "[tape.search]: 1 matches"}),
]
monkeypatch.setattr(builtin_tools, "_get_agent", lambda _context: _FakeAgent(entries))

output = await tape_search.run(query="x", context=ToolContext(tape="tape", run_id="run", state={}))

assert output.splitlines()[0] == "[tape.search]: 1 matches (1 filtered)"


@pytest.mark.asyncio
async def test_tape_search_reports_zero_filtered_explicitly(monkeypatch) -> None:
entries = [
_FakeEntry(date="2026-01-01T00:00:00Z", payload={"content": "a"}),
_FakeEntry(date="2026-01-01T00:00:01Z", payload={"content": "b"}),
]
monkeypatch.setattr(builtin_tools, "_get_agent", lambda _context: _FakeAgent(entries))

output = await tape_search.run(query="x", context=ToolContext(tape="tape", run_id="run", state={}))

assert output.splitlines()[0] == "[tape.search]: 2 matches (0 filtered)"
Loading