fix(learn): pass explicit model in tests to avoid API key requirement

SessionAnalyzer() without a model calls _detect_default_model() which
raises when no API keys are set (e.g., in CI). Pass model="test-model"
in the three tests that mock _call_llm.
This commit is contained in:
Tejas Chopra 2026-03-07 14:59:48 -08:00
parent 4d14012c2f
commit da481a359b
3 changed files with 16 additions and 22 deletions

View file

@ -62,9 +62,7 @@ class SessionAnalyzer:
def __init__(self, model: str | None = None):
self.model = model
def analyze(
self, project: ProjectInfo, sessions: list[SessionData]
) -> AnalysisResult:
def analyze(self, project: ProjectInfo, sessions: list[SessionData]) -> AnalysisResult:
"""Analyze sessions and produce recommendations via LLM."""
all_calls = [tc for s in sessions for tc in s.tool_calls]
failed_calls = [tc for tc in all_calls if tc.is_error]
@ -134,7 +132,9 @@ def _build_digest(project: ProjectInfo, sessions: list[SessionData]) -> str:
for session in sessions:
if chars_used > char_budget:
lines.append(f"... (remaining {len(sessions) - sessions.index(session)} sessions truncated)")
lines.append(
f"... (remaining {len(sessions) - sessions.index(session)} sessions truncated)"
)
break
session_header = (
@ -179,7 +179,7 @@ def _format_event(event: SessionEvent) -> str | None:
if event.type == "user_message" and event.text.strip():
text = event.text.strip()[:300]
return f" [{event.msg_index}] USER: \"{text}\""
return f' [{event.msg_index}] USER: "{text}"'
if event.type == "interruption":
return f" [{event.msg_index}] INTERRUPTED: {event.text[:150]}"
@ -188,7 +188,7 @@ def _format_event(event: SessionEvent) -> str | None:
return (
f" [{event.msg_index}] SUBAGENT: {event.agent_tool_count} tool calls, "
f"{event.agent_tokens:,} tokens, {event.agent_duration_ms / 1000:.1f}s "
f"— prompt: \"{event.agent_prompt[:100]}\""
f'— prompt: "{event.agent_prompt[:100]}"'
)
return None
@ -384,7 +384,5 @@ class FailureAnalyzer:
def __init__(self) -> None:
self._analyzer = SessionAnalyzer()
def analyze(
self, project: ProjectInfo, sessions: list[SessionData]
) -> AnalysisResult:
def analyze(self, project: ProjectInfo, sessions: list[SessionData]) -> AnalysisResult:
return self._analyzer.analyze(project, sessions)

View file

@ -240,9 +240,7 @@ class ClaudeCodeScanner(ConversationScanner):
total_input_tokens += usage.get("cache_creation_input_tokens", 0)
total_output_tokens += usage.get("output_tokens", 0)
elif line_type == "user":
self._extract_tool_results(
d, tool_uses, tool_calls, events, msg_index, ts
)
self._extract_tool_results(d, tool_uses, tool_calls, events, msg_index, ts)
self._extract_user_events(d, events, msg_index, ts)
except (OSError, UnicodeDecodeError) as e:
@ -251,12 +249,8 @@ class ClaudeCodeScanner(ConversationScanner):
# Also wrap tool_calls as events for unified access
for tc in tool_calls:
if not any(
e.type == "tool_call" and e.tool_call is tc for e in events
):
events.append(
SessionEvent(type="tool_call", msg_index=tc.msg_index, tool_call=tc)
)
if not any(e.type == "tool_call" and e.tool_call is tc for e in events):
events.append(SessionEvent(type="tool_call", msg_index=tc.msg_index, tool_call=tc))
events.sort(key=lambda e: e.msg_index)
return SessionData(
@ -332,7 +326,9 @@ class ClaudeCodeScanner(ConversationScanner):
)
tool_calls.append(tc)
events.append(
SessionEvent(type="tool_call", msg_index=msg_index, timestamp=timestamp, tool_call=tc)
SessionEvent(
type="tool_call", msg_index=msg_index, timestamp=timestamp, tool_call=tc
)
)
# Extract subagent summary from toolUseResult metadata

View file

@ -261,7 +261,7 @@ class TestSessionAnalyzer:
"memory_file_rules": [],
}
analyzer = SessionAnalyzer()
analyzer = SessionAnalyzer(model="test-model")
sessions = [
SessionData(
session_id="s1",
@ -283,7 +283,7 @@ class TestSessionAnalyzer:
def test_handles_llm_failure_gracefully(self, mock_call_llm: MagicMock):
mock_call_llm.side_effect = RuntimeError("API key not set")
analyzer = SessionAnalyzer()
analyzer = SessionAnalyzer(model="test-model")
sessions = [
SessionData(
session_id="s1",
@ -309,7 +309,7 @@ class TestSessionAnalyzer:
]
sessions = [SessionData(session_id="s1", tool_calls=[tc], events=events)]
analyzer = SessionAnalyzer()
analyzer = SessionAnalyzer(model="test-model")
analyzer.analyze(_project(), sessions)
# Check that the digest passed to the LLM includes user message