fix(agents): preserve thinking blocks in latest assistant message during compaction#25381
fix(agents): preserve thinking blocks in latest assistant message during compaction#25381Nipurn123 wants to merge 9 commits intoopenclaw:mainfrom
Conversation
- Add sendDiceTelegram function to telegram/send.ts - Support all dice emojis: 🎲 🎯 🏀 ⚽ 🎳 🎰 - Return dice value in result so agent knows outcome - Wire into message tool via handleTelegramAction - Default enabled via sendDice action gate Closes openclaw#25263
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Replace hardcoded provider checks with a provider handler registry pattern: - Add ProviderHandler type with createWrapper and enabledWhen hooks - Create providerHandlers registry with entries for: - anthropic: beta headers - openrouter: app headers + reasoning effort + system cache - amazon-bedrock: non-Anthropic cache disable - zai/z-ai: tool_stream injection - *: OpenAI Responses store wrapper (applies to all) - Simplify applyExtraParamsToAgent with registry iteration Benefits: - Easier to add new providers - Clearer separation of concerns - Each provider's logic is self-contained Closes openclaw#25311
…ing compaction Anthropic's API requires that thinking/redacted_thinking blocks in the latest assistant message remain exactly as received. The dropThinkingBlocks() function was stripping ALL thinking blocks from ALL assistant messages, causing API 400 errors during context compaction in longer conversations. Now the function preserves thinking blocks in the latest assistant message while still stripping them from older messages (needed for GitHub Copilot compatibility). Fixes openclaw#25347
| const to = readStringParam(params, "to", { required: true }); | ||
| const emoji = readStringParam(params, "emoji"); | ||
| if (emoji && !["🎲", "🎯", "🏀", "⚽", "🎳", "🎰"].includes(emoji)) { | ||
| throw new Error(`Invalid dice emoji: ${emoji}. Must be one of: 🎲 🎯 🏀 ⚽🎳 🎰`); |
There was a problem hiding this comment.
Missing space in error message
The error message is missing a space between ⚽ and 🎳. The validation array on line 382 correctly lists all 6 emoji as separate items, but the user-facing error message concatenates two of them.
| throw new Error(`Invalid dice emoji: ${emoji}. Must be one of: 🎲 🎯 🏀 ⚽🎳 🎰`); | |
| throw new Error(`Invalid dice emoji: ${emoji}. Must be one of: 🎲 🎯 🏀 ⚽ 🎳 🎰`); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tools/telegram-actions.ts
Line: 383
Comment:
**Missing space in error message**
The error message is missing a space between `⚽` and `🎳`. The validation array on line 382 correctly lists all 6 emoji as separate items, but the user-facing error message concatenates two of them.
```suggestion
throw new Error(`Invalid dice emoji: ${emoji}. Must be one of: 🎲 🎯 🏀 ⚽ 🎳 🎰`);
```
How can I resolve this? If you propose a fix, please make it concise.…ompaction-25347 # Conflicts: # src/agents/pi-embedded-runner/extra-params.ts
|
This pull request has been automatically marked as stale due to inactivity. |
xiaoyaner0201
left a comment
There was a problem hiding this comment.
🔍 Duplicate PR Group: Anthropic Thinking Block Compaction
This PR is one of 7 open PRs addressing the same issue: Anthropic thinking/redacted_thinking blocks from older assistant messages cause API errors during context compaction.
Related PRs
| PR | Author | Date | Approach | Preserves latest | redacted_thinking | Compaction path | Tests | Clean diff |
|---|---|---|---|---|---|---|---|---|
| #24261 | @Vaibhavee89 | 02-23 | Guard functions + logging | N/A (no actual strip) | Detect only | ❌ | Medium | ✅ |
| #25381 | @Nipurn123 | 02-24 | Modify dropThinkingBlocks skip latest |
✅ | ❌ | ❌ | Good | ❌ (bundles sendDice) |
| #27142 | @slatem | 02-26 | Extend dropThinkingBlocks to Anthropic |
❌ (strips all) | ✅ | ❌ | Limited | ✅ |
| #39919 | @taw0002 | 03-08 | New strip function in sanitizeSessionHistory | ✅ | ✅ | ❌ | Good | ✅ |
| #39940 | @liangruochong44-ui | 03-08 | Policy flag for Anthropic | ❌ (strips all) | ✅ | ❌ | Medium | ❌ (bundles cron/SQLite/UI) |
| #43783 | @coletoncodes | 03-12 | New stripThinkingFromNonLatestAssistant + compact path |
✅ | ✅ | ✅ | Best | ✅ |
| #44650 | @rikisann | 03-13 | Runtime monkey-patch of node_modules | ✅ | ✅ | ❌ | None |
Analysis
After reading all 7 diffs:
#43783 is the strongest candidate. It:
- Creates a standalone
stripThinkingFromNonLatestAssistant()without changingdropThinkingBlockssemantics (preserves Copilot behavior) - Integrates via existing
policy.preserveSignaturesflag (proper transcript policy mechanism) - Only PR that also fixes the compaction path (
compact.ts) — others only fixsanitizeSessionHistory - Handles both
thinkingandredacted_thinkingblock types - Clean diff with comprehensive tests (toolResult interleaving, empty blocks, reference equality)
#39919 is a close second (same core function, clean diff, good tests) but misses the compaction path.
Notable discovery from #44650: sanitizeSurrogates may corrupt thinking block signatures — worth investigating separately even though the monkey-patch approach is not viable.
Not recommended: #27142 and #39940 strip thinking from ALL messages including latest (breaks multi-turn quality). #25381 and #39940 bundle unrelated changes.
Similarities identified via embedding-based clustering (cosine > 0.82). Maintainers: #43783 appears ready for review.
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing as duplicate; this was superseded by #58916. |
Summary
dropThinkingBlocks()to preserve thinking blocks in the latest assistant message (Anthropic API requirement)Root Cause
The Anthropic API requires that thinking/redacted_thinking blocks in the latest assistant message remain exactly as received. The
dropThinkingBlocks()function was stripping ALL thinking blocks from ALL assistant messages, causing this error during longer conversations:Changes
src/agents/pi-embedded-runner/thinking.ts- Added logic to find and skip the latest assistant message when dropping thinking blockssrc/agents/pi-embedded-runner/thinking.test.ts- Added 4 new tests for latest assistant preservationsrc/agents/pi-embedded-runner.sanitize-session-history.test.ts- Updated 3 tests + added 1 new test for the behaviorTesting
pnpm checkpasses (lint/format)Greptile Summary
This PR bundles three independent changes: (1) a fix for Anthropic API 400 errors by preserving thinking blocks in the latest assistant message during context compaction, (2) a refactor of
extra-params.tsfrom inline provider if/else to a registry-based pattern, and (3) a new TelegramsendDiceaction with full threading/gating support plus orphan transcript cleanup on gateway startup.thinking.ts):dropThinkingBlocks()now scans backward to find the latest assistant message and preserves it intact, only stripping thinking blocks from older assistant messages. This directly fixes the API rejection error. Well-tested with 4 new unit tests and updated integration tests.extra-params.ts): Refactored provider-specific stream wrapper logic into aMap<string, ProviderHandler[]>registry with a*wildcard for universal handlers. Functionally equivalent to the old code — Map insertion order preserves the original application sequence.sendDicesupport across the full stack — types, send function, action handler, plugin adapter, and action spec. Includes emoji validation, threading, and gating. Minor formatting bug in the error message (missing space between emojis).server-startup.ts): NewcleanupOrphanTranscripts()archives.jsonltranscript files not referenced in the session store, with a safety threshold of 10 files before cleanup activates.Confidence Score: 4/5
src/agents/tools/telegram-actions.tshas a minor formatting bug in the dice emoji error message (missing space between ⚽ and 🎳).Last reviewed commit: 70f78dd