Skip to content

fix(agents): respect markdown code spans when stripping thinking tags#939

Closed
ngutman wants to merge 1 commit intoopenclaw:mainfrom
ngutman:fix/thinking-tag-in-backticks
Closed

fix(agents): respect markdown code spans when stripping thinking tags#939
ngutman wants to merge 1 commit intoopenclaw:mainfrom
ngutman:fix/thinking-tag-in-backticks

Conversation

@ngutman
Copy link
Copy Markdown
Contributor

@ngutman ngutman commented Jan 15, 2026

Summary

The stripBlockTags function in pi-embedded-subscribe.ts was incorrectly matching <thinking> tags inside markdown code spans (backticks), causing message content to be truncated.

For example, a message like:

fixes leaked `<thinking>` tags

would have everything after the backtick-enclosed <thinking> stripped, because the regex did not understand markdown context.

Changes

  • Added findCodeSpanRanges() helper to identify inline code (`) and fenced code blocks (```) in text
  • Added isInsideCodeSpan() helper to check if an index falls within code spans
  • Modified stripBlockTags() to skip thinking tag matches that fall inside code spans
  • Added 3 tests for the new behavior

Test Plan

  • 3 new unit tests for code span awareness pass
  • All 53 pi-embedded-subscribe tests pass
  • TypeScript type check passes

Context

When discussing code changes related to thinking tags (e.g., documenting what was fixed), the streaming output would be incorrectly truncated.

🤖 Generated with Clawdbot

The stripBlockTags function in pi-embedded-subscribe.ts was incorrectly
matching <thinking> tags inside markdown code spans (backticks), causing
message content to be truncated.

For example, a message like:
  'fixes leaked `<thinking>` tags'
would have everything after the backtick-enclosed <thinking> stripped,
because the regex didn't understand markdown context.

Changes:
- Added findCodeSpanRanges() helper to identify inline code (`) and
  fenced code blocks (```) in text
- Added isInsideCodeSpan() helper to check if an index falls within
  code spans
- Modified stripBlockTags() to skip thinking tag matches that fall
  inside code spans
- Added 3 tests for the new behavior

Fixes message truncation when discussing thinking tags in code examples.
@steipete
Copy link
Copy Markdown
Contributor

Ha what model was that? That's some hacky slop xD

  Yes, current approach is hacky. Cleaner path: reuse existing markdown
  fence parser + add a tiny inline-code span parser with streaming state.
  No bespoke regex-by-index per call.

  Clean approach outline:

  - Reuse parseFenceSpans from src/markdown/fences.ts for fenced blocks
    (handles indent + 3+ ticks/tilde).
  - Add parseInlineCodeSpans once in src/markdown/inline-code.ts (single-
    pass state machine; supports multiple backtick lengths; treats
    unclosed as open-to-end).
  - In stripBlockTags, skip matches if isInFenceSpan || isInInlineSpan.
  - Keep state across chunks: track inlineCodeOpen + inlineTickLen in
    state.blockState, so chunked streaming can’t break inline detection.

@steipete
Copy link
Copy Markdown
Contributor

Appreciate the bug report tho!

@ngutman
Copy link
Copy Markdown
Contributor Author

ngutman commented Jan 15, 2026

@steipete running slopus - anthropic/claude-opus-4-5 🙈
should have chose codex for this haha

@ngutman
Copy link
Copy Markdown
Contributor Author

ngutman commented Jan 15, 2026

Closing - fix already merged to main in 7e1e7ba by @steipete. Thanks for the review feedback!

(clawdbot did that ^^ 🦞)

@ngutman ngutman closed this Jan 15, 2026
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.

2 participants