Fixes four production bugs hit while running DeepTutor from source (Option 2) against Claude Opus 4.8 with an Obsidian vault KB. Three are request/tool failures that break core flows; one is a Windows-only stability bug that silently swallows backend tracebacks. Each fix ships with regression tests. #653
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Fixes four production bugs hit while running DeepTutor from source (Option 2)
against Claude Opus 4.8 with an Obsidian vault KB. Three are request/tool
failures that break core flows; one is a Windows-only stability bug that
silently swallows backend tracebacks. Each fix ships with regression tests.
Bugs & Fixes
1. Anthropic: exceeds 4 cache_control breakpoints → 400 invalid_params
AnthropicProvider._apply_cache_controlcould emit system(1) + message(1) +tools(N)
cache_controlmarkers. With many tools mounted (e.g. the 9 Obsidiantools), the total exceeded Anthropic's hard limit of 4, so every request failed:
Fix: budget the breakpoints to a max of 4 across tools + system + messages,
keeping the highest-value tool breakpoint first.
deeptutor/services/llm/provider_core/anthropic_provider.py2. Anthropic:
temperaturesent to Opus 4.7+ → 400 invalid_paramstemperatureis deprecated on Opus 4.7 and later; sending it makes those modelsreject the request. The guard only matched
opus-4-7, soopus-4-8(and 4.9/4.10+) still broke:
Fix: omit
temperatureforopus-4-(7|8|9|10+)viare.search(r"opus-4-([7-9]|\d{2,})", model_name).deeptutor/services/llm/provider_core/anthropic_provider.py3. obsidian_read crashes on
date:frontmatter → tool failureObsidian notes commonly carry a
date:field.yaml.safe_loadparses it into aPython
datetime.date, whichjson.dumpscannot serialize, so any such notefailed to read:
Fix:
_ok()now callsjson.dumps(..., default=str)so date/datetimevalues render as strings.
deeptutor/capabilities/obsidian/tools.py4. Launcher: GBK console crash kills the output-draining thread (Windows)
_stream_outputused bareprint(). On a GBK/cp936 Windows console, a non-CP936char (e.g.
✓) in a subprocess line raisedUnicodeEncodeError, killing thedrain thread. That both hid backend tracebacks and could block the backend once
the pipe buffer filled (observed as a hang/freeze).
Fix: guard
print()with aUnicodeEncodeErrorfallback that re-encodeswith
errors="replace".deeptutor/runtime/launcher.pyTests
tests/services/llm/test_anthropic_cache_control.py— ≤4 cache blocks across tool countstests/services/llm/test_anthropic_temperature.py— temperature omitted for Opus 4.7+, sent for older modelstests/capabilities/obsidian/test_obsidian_read_date.py— obsidian_read handles date frontmatterAll 16 tests pass. Each fix was verified two-way (revert → fails with the exact
production error; restore → passes).
Environment
Python 3.12.7 · Windows 10 · provider routed via zenmux.ai · model claude-opus-4-8.
All reactions