diff --git a/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx b/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx
index 4f22468157..08b46863cf 100644
--- a/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx
+++ b/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx
@@ -74,6 +74,18 @@ describe('ThinkBlock', () => {
expect(screen.getByText('Thinking content')).toBeInTheDocument()
})
+ it('should render think block when dataThink is true', () => {
+ renderWithContext(
+
+ Thinking content
+ ,
+ true,
+ )
+
+ expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
+ expect(screen.getByText('Thinking content')).toBeInTheDocument()
+ })
+
it('should render thought state when content has ENDTHINKFLAG', () => {
renderWithContext(
diff --git a/web/app/components/base/markdown-blocks/think-block.tsx b/web/app/components/base/markdown-blocks/think-block.tsx
index 184ed89274..c3bd411cbe 100644
--- a/web/app/components/base/markdown-blocks/think-block.tsx
+++ b/web/app/components/base/markdown-blocks/think-block.tsx
@@ -72,13 +72,15 @@ const useThinkTimer = (children: any) => {
type ThinkBlockProps = React.ComponentProps<'details'> & {
'data-think'?: boolean
+ 'dataThink'?: boolean
}
const ThinkBlock = ({ children, ...props }: ThinkBlockProps) => {
const { elapsedTime, isComplete } = useThinkTimer(children)
const displayContent = removeEndThink(children)
const { t } = useTranslation()
- const { 'data-think': isThink = false, className, open, ...rest } = props
+ const { 'data-think': dataThinkAttr, dataThink: dataThinkProp, className, open, ...rest } = props
+ const isThink = Boolean(dataThinkAttr ?? dataThinkProp)
if (!isThink)
return ({children} )
diff --git a/web/app/components/base/markdown/streamdown-wrapper.tsx b/web/app/components/base/markdown/streamdown-wrapper.tsx
index 46db301adb..173923fdc7 100644
--- a/web/app/components/base/markdown/streamdown-wrapper.tsx
+++ b/web/app/components/base/markdown/streamdown-wrapper.tsx
@@ -43,8 +43,9 @@ const mathPlugin = createMathPlugin({
/**
* Allowed HTML tags and their permitted data attributes for rehype-sanitize.
- * Keys = tag names to allow; values = attribute names in **hast** property format
- * (camelCase, e.g. `dataThink` for `data-think`).
+ * Keys = tag names to allow; values = attribute names used by the sanitize schema.
+ * Prefer **hast** property format (camelCase, e.g. `dataThink` for `data-think`),
+ * but include kebab-case variants when different parser paths can emit both forms.
*
* Prefer explicit attribute lists over wildcards (e.g. `data*`) to
* minimise the attack surface when LLM-generated content is rendered.
@@ -55,7 +56,7 @@ const ALLOWED_TAGS: Record = {
input: ['type', 'name', 'value', 'placeholder', 'checked', 'dataTip', 'dataOptions'],
textarea: ['name', 'placeholder', 'value'],
label: ['htmlFor'],
- details: ['dataThink'],
+ details: ['dataThink', 'data-think'],
video: ['src'],
audio: ['src'],
source: ['src'],