Skip to content

fix: enable thinking block pruning — reasoning/message hash visibility#17

Merged
tuanhung303 merged 4 commits intomasterfrom
refactor/deduplicate-and-simplify
Feb 7, 2026
Merged

fix: enable thinking block pruning — reasoning/message hash visibility#17
tuanhung303 merged 4 commits intomasterfrom
refactor/deduplicate-and-simplify

Conversation

@tuanhung303
Copy link
Owner

Summary

  • Fix reasoning_hash and message_hash visibility — hashes were injected into text parts then stripped before the LLM could see them, making thinking block pruning impossible
  • Primary channel: inject hashes into tool outputs (never stripped) with text-part fallback and synthetic-part last resort
  • Selective stripping: stripAllHashTagsFromMessages now preserves reasoning_hash and message_hash in text parts for LLM visibility
  • Pipeline fix: injectHashesIntoAssistantMessages no longer destroys reasoning_hash tags injected by the prior pipeline step

Root Cause

hooks.ts L117: injectHashesIntoReasoningBlocks() → appends <reasoning_hash> to text part
hooks.ts L124: injectHashesIntoAssistantMessages() → stripHashTags() destroys <reasoning_hash>
hooks.ts L176: stripAllHashTagsFromMessages() → strips ALL remaining tags from text parts

Result: agents could never see reasoning hashes → could never prune their own thinking blocks.

Changes

File Change
lib/state/hash-registry.ts Added stripHashTagsSelective() — strips by type, preserves specified types
lib/messages/prune.ts Rewrote hash injection to prefer tool outputs; selective stripping preserves reasoning/message hashes
lib/prompts/context-spec.ts Updated agent instructions documenting hash locations
tests/e2e/thinking-blocks.test.ts Added 8 round-trip pipeline tests
tests/fixtures/mock-client.ts Added missing state fields for test compatibility

Verified

  • 555 tests passing, 0 regressions
  • Live tested: agents can now see and prune both reasoning_hash and message_hash across all providers

- Consolidate 3 duplicate stableStringify/deterministicStringify into single export
- Remove duplicate INPUT_METADATA_KEYS, stripHashTags, applyPatternReplacements from prune.ts
- Wire applyPatternReplacements into message transform pipeline (was defined but never called)
- Fix persistence bug: saveSessionState now includes cursors, todos, discardHistory
- Delete dead lib/config-cache.ts (113 lines, 0 imports)
- Extract 6 supersede strategies from 405-line syncToolCache into named functions
- Replace extractParameterKey if-else chain with lookup map
- Fix circular dependency in shared-utils.ts import
…lity

Reasoning and message hashes were injected into text parts then stripped
by stripAllHashTagsFromMessages before the LLM could see them. Now:
- Primary channel: inject into last completed tool output (never stripped)
- Fallback: text parts with selective stripping (preserves reasoning/message hashes)
- Last resort: synthetic text part for reasoning-only messages

Partial fix: message_hash now visible, reasoning_hash still not appearing
when no tool calls exist in the response. Further investigation needed.
injectHashesIntoAssistantMessages was calling stripHashTags() on text
parts for idempotency, which destroyed reasoning_hash tags injected by
the prior pipeline step. Now uses stripHashTagsSelective() to preserve
reasoning hashes while still stripping other tag types.
@tuanhung303 tuanhung303 merged commit db380b8 into master Feb 7, 2026
3 checks passed
@tuanhung303 tuanhung303 deleted the refactor/deduplicate-and-simplify branch February 9, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant