-
Notifications
You must be signed in to change notification settings - Fork 2
fix(sidequest): rebuild_cursors only scans ToolOutput, misses ToolResult from native tool-use providers #2114
Description
Summary
SidequestState::rebuild_cursors scans for MessagePart::ToolOutput but the native tool execution path stores results as MessagePart::ToolResult. This means SideQuest eviction silently does nothing when using OpenAI, Claude, or any provider with supports_tool_use() == true.
Root cause
crates/zeph-core/src/agent/tool_execution/legacy.rs:20-26 dispatches to native or legacy based on provider.supports_tool_use():
- Native path (
native.rs): stores tool results asMessagePart::ToolResult { tool_use_id, content, is_error } - Legacy path (
legacy.rs): stores tool results asMessagePart::ToolOutput { tool_name, body, compacted_at }
SidequestState::rebuild_cursors (crates/zeph-core/src/agent/sidequest.rs:106) pattern-matches only MessagePart::ToolOutput. With native providers, all tool outputs are stored as ToolResult — so the cursor list is always empty.
Evidence
CI-75 live test with OpenAI router + [memory.sidequest] enabled = true, interval_turns = 2:
2026-03-22T12:02:04.826488Z DEBUG zeph_core::agent: sidequest: no eligible cursors
2026-03-22T12:03:01.225734Z DEBUG zeph_core::agent: sidequest: no eligible cursors
The tick() fires correctly at turn 2 and 4, but rebuild_cursors finds zero matching parts.
Severity
MEDIUM — SideQuest is disabled by default (enabled = false). No production impact today. But functionally broken for the most common providers (OpenAI, Claude). Works only with Ollama legacy path.
Fix
rebuild_cursors must also scan MessagePart::ToolResult entries. The eviction logic (apply_eviction) needs to handle the ToolResult variant alongside ToolOutput. The compacted_at concept (used in ToolOutput) needs an equivalent for ToolResult — either add a evicted flag to ToolResult or replace its content with a tombstone like [evicted by sidequest].
Alternatively, unify the two message part variants into a single ToolResult with an optional compacted_at field.
Filed
CI-75, 2026-03-22