From 263ea65ed6cbe08fb114a48d9de20b4ebb8aeb98 Mon Sep 17 00:00:00 2001 From: Gyanu Mayank Date: Fri, 4 Sep 2026 10:12:47 +0530 Subject: [PATCH] Keep long /continue sessions visible when the first user prompt sits past 32KB Head/tail preview windows miss tool-heavy logs whose first real user text is in the middle of the file, so list_sessions() dropped them. Scan extra windows up to the grep budget only when those ends are empty. --- frontends/continue_cmd.py | 43 +++++++++++++++++++++++ frontends/tests/test_continue_preview.py | 44 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 frontends/tests/test_continue_preview.py diff --git a/frontends/continue_cmd.py b/frontends/continue_cmd.py index 3e926c11c..e3554a0f5 100644 --- a/frontends/continue_cmd.py +++ b/frontends/continue_cmd.py @@ -261,6 +261,49 @@ def _preview_from_file(path): lu = _last_user(tail_s) or _last_user(head.decode('utf-8', errors='replace')) if lu: return ' '.join(lu.split())[:120] + scanned = _preview_from_scan(path, sz) + if scanned: + return scanned + return '' + + +def _first_real_user(text): + """First typed user prompt in `text`, skipping tool_result continuations.""" + for label, body in _BLOCK_RE.findall(text or ''): + if label == 'Prompt': + t = _user_text(body) + if t: + return t + return '' + + +def _preview_from_scan(path, sz): + """Find a user prompt that sits between the 32KB head and tail windows. + + Long tool-heavy sessions often park the first real user text past the head + window, with no in the tail either. list_sessions() then drops + the log. Scan extra windows up to _GREP_WIN only when head+tail missed. + """ + if sz <= _PREVIEW_WIN * 2: + return '' + limit = min(sz, _GREP_WIN) + try: + with open(path, 'rb') as fh: + offset = 0 + carry = b'' + while offset < limit: + fh.seek(offset) + chunk = fh.read(_PREVIEW_WIN) + if not chunk: + break + text = (carry + chunk).decode('utf-8', errors='replace') + t = _first_real_user(text) + if t: + return ' '.join(t.split())[:120] + carry = chunk[-4096:] + offset += len(chunk) + except OSError: + return '' return '' diff --git a/frontends/tests/test_continue_preview.py b/frontends/tests/test_continue_preview.py new file mode 100644 index 000000000..9d8f72f08 --- /dev/null +++ b/frontends/tests/test_continue_preview.py @@ -0,0 +1,44 @@ +"""Preview extraction for /continue when the first user prompt sits past the head window.""" +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent.parent +sys.path.insert(0, str(ROOT / "frontends")) + +from continue_cmd import _preview_from_file, list_sessions # noqa: E402 + + +def _block(prompt_obj, response_text="ok"): + prompt = json.dumps(prompt_obj, ensure_ascii=False) + return ( + f"=== Prompt === extra\n{prompt}\n" + f"=== Response === extra\n[{{'type': 'text', 'text': {response_text!r}}}]\n" + ) + + +def _tool_block(): + return _block( + {"role": "user", "content": [{"type": "tool_result", "content": "x" * 400}]} + ) + + +def test_preview_finds_user_prompt_past_32kb_head(tmp_path, monkeypatch): + log_dir = tmp_path / "temp" / "model_responses" + log_dir.mkdir(parents=True) + path = log_dir / "model_responses_4242.txt" + + user_text = "Index remaining PDFs using focr house style and skip Jira keys." + prefix = _tool_block() * 80 # well over 32KB of tool_result rounds + suffix = _tool_block() * 80 + middle = _block({"role": "user", "content": [{"type": "text", "text": user_text}]}) + path.write_text(prefix + middle + suffix, encoding="utf-8") + assert path.stat().st_size > 64 * 1024 + + preview = _preview_from_file(str(path)) + assert "Index remaining PDFs" in preview + + monkeypatch.setattr("continue_cmd._LOG_GLOB", str(log_dir / "model_responses_*.txt")) + monkeypatch.setattr("continue_cmd._ROUNDS_CACHE_PATH", str(tmp_path / "continue_rounds_cache.json")) + sessions = list_sessions() + assert any("Index remaining PDFs" in item[2] for item in sessions)