From d4433c3f6680ede3d22718d2396d18ed9604c8b8 Mon Sep 17 00:00:00 2001 From: ignorejjj Date: Mon, 29 Jun 2026 10:22:17 +0800 Subject: [PATCH 1/2] fix(llm): report Responses API cached_tokens so cache hits are visible openai_responses parsed only input/output tokens, so gpt-5.x via the Responses API always logged cache_read=0 even when the prefix was cached. Split cached_tokens out of input_tokens (mirroring openai_compat) so token stats are honest and total_input_tokens isn't double-counted. --- src/core/llm/openai_responses.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/llm/openai_responses.py b/src/core/llm/openai_responses.py index abbab52..b278381 100644 --- a/src/core/llm/openai_responses.py +++ b/src/core/llm/openai_responses.py @@ -392,8 +392,18 @@ def _parse_response(self, raw: Any) -> LLMResponse: usage = Usage() raw_usage = getattr(raw, "usage", None) if raw_usage: - usage.input_tokens = int(getattr(raw_usage, "input_tokens", 0) or 0) + total_input = int(getattr(raw_usage, "input_tokens", 0) or 0) usage.output_tokens = int(getattr(raw_usage, "output_tokens", 0) or 0) + # Responses counts cached prompt tokens inside ``input_tokens`` (under + # ``input_tokens_details.cached_tokens``); split them out so cache hits + # are visible and ``total_input_tokens`` doesn't double-count. + details = getattr(raw_usage, "input_tokens_details", None) + cached = getattr(details, "cached_tokens", None) if details is not None else None + if cached is None and isinstance(details, dict): + cached = details.get("cached_tokens") + cached = int(cached or 0) + usage.input_tokens = max(0, total_input - cached) + usage.cache_read_tokens = cached stop_reason = "tool_use" if tool_calls else "end_turn" if getattr(raw, "status", None) == "incomplete": From ca95328668e9743216e78a5c0e1f7422bdaa47eb Mon Sep 17 00:00:00 2001 From: ignorejjj Date: Mon, 29 Jun 2026 10:22:17 +0800 Subject: [PATCH 2/2] docs(examples): default algotune_knn to auto interaction mode review mode hangs an unattended/headless run waiting for input; auto is the right default for a copy-paste first run. --- examples/algotune_knn/research_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/algotune_knn/research_config.yaml b/examples/algotune_knn/research_config.yaml index b11c58c..3607ccb 100644 --- a/examples/algotune_knn/research_config.yaml +++ b/examples/algotune_knn/research_config.yaml @@ -33,4 +33,4 @@ executor: max_turns: 30 ui: - interaction_mode: review # auto | direction | review | collaborative + interaction_mode: auto # auto | direction | review | collaborative