@@ -68,8 +68,11 @@ interface AssistantMessageProps {
6868}
6969
7070const COMPLETE_ARTIFACT_BLOCK_RE = / < d e v o n z A r t i f a c t [ ^ > ] * > [ \s \S ] * ?< \/ d e v o n z A r t i f a c t > / g;
71+ const COMPLETE_ACTION_BLOCK_RE = / < d e v o n z A c t i o n [ ^ > ] * > [ \s \S ] * ?< \/ d e v o n z A c t i o n > / g;
7172const UNCLOSED_ARTIFACT_RE = / < d e v o n z A r t i f a c t [ ^ > ] * > [ \s \S ] * $ / ;
73+ const UNCLOSED_ACTION_RE = / < d e v o n z A c t i o n [ ^ > ] * > [ \s \S ] * $ / ;
7274const LEFTOVER_TAG_RE = / < \/ ? d e v o n z (?: A r t i f a c t | A c t i o n ) [ ^ > ] * > / g;
75+ const PARTIAL_DEVONZ_TAG_RE = / < d e v o n z [ A - Z a - z ] * (?: \s [ ^ > ] * ) ? $ / ;
7376
7477/** Matches complete or partial `</assistant>` / `<assistant>` XML tags that LLMs sometimes emit */
7578const ASSISTANT_TAG_RE = / < \/ ? a s s i s t (?: a n t ) ? > | < \/ a s s i s (?: t (?: a (?: n (?: t ) ? ) ? ) ? ) ? \s * $ / g;
@@ -78,22 +81,36 @@ const ASSISTANT_TAG_RE = /<\/?assist(?:ant)?>|<\/assis(?:t(?:a(?:n(?:t)?)?)?)?\s
7881const CHAIN_OF_THOUGHT_BLOCK_RE = / < c h a i n _ o f _ t h o u g h t > [ \s \S ] * ?< \/ c h a i n _ o f _ t h o u g h t > / g;
7982const CHAIN_OF_THOUGHT_TAG_RE = / < \/ ? c h a i n _ o f _ t h o u g h t \s * \/ ? > / g;
8083
84+ /** Matches complete fenced code blocks that leaked outside artifact wrappers */
85+ const LEAKED_CODE_BLOCK_RE = / ` ` ` [ \w ] * \n [ \s \S ] * ?` ` ` / g;
86+
87+ /** Matches unclosed fenced code blocks still being streamed */
88+ const UNCLOSED_CODE_BLOCK_RE = / ` ` ` [ \w ] * \n [ \s \S ] * $ / ;
89+
8190/**
82- * Strip raw artifact/action markup that leaks through the parser during
83- * streaming. Complete blocks are removed first, then everything after an
84- * unclosed `<devonzArtifact` tag (whose closing tag hasn't arrived yet) is
85- * chopped — this prevents code content from appearing in the chat bubble
86- * while the AI is still generating.
91+ * Strip raw artifact/action markup — including file CONTENT — that leaks
92+ * through the parser during streaming.
93+ *
94+ * 1. Complete `<devonzArtifact>` blocks (wrapper + all actions + content)
95+ * 2. Complete `<devonzAction>` blocks (handles cases where the parser
96+ * already consumed the artifact wrapper but left action tags + code)
97+ * 3. Everything after an unclosed `<devonzArtifact` or `<devonzAction`
98+ * tag (content still streaming)
99+ * 4. Leftover individual open/close tags
100+ * 5. Partial `<devonz...` tags mid-stream (e.g. `<devonzArt`)
87101 *
88- * Also strips stray `</assistant>` or partial fragments like `</assis`
89- * that some models emit at the end of their response.
102+ * Also strips stray `</assistant>` fragments and `<chain_of_thought>` blocks.
90103 */
91104function stripRawArtifactTags ( text : string ) : string {
92105 let result = text ;
93106
94- if ( result . includes ( 'devonzA' ) ) {
95- result = result . replace ( COMPLETE_ARTIFACT_BLOCK_RE , '' ) . replace ( UNCLOSED_ARTIFACT_RE , '' ) ;
107+ if ( result . includes ( '<devonz' ) ) {
108+ result = result . replace ( COMPLETE_ARTIFACT_BLOCK_RE , '' ) ;
109+ result = result . replace ( COMPLETE_ACTION_BLOCK_RE , '' ) ;
110+ result = result . replace ( UNCLOSED_ARTIFACT_RE , '' ) ;
111+ result = result . replace ( UNCLOSED_ACTION_RE , '' ) ;
96112 result = result . replace ( LEFTOVER_TAG_RE , '' ) ;
113+ result = result . replace ( PARTIAL_DEVONZ_TAG_RE , '' ) ;
97114 }
98115
99116 if ( result . includes ( 'assis' ) || result . includes ( 'Assis' ) ) {
@@ -104,6 +121,13 @@ function stripRawArtifactTags(text: string): string {
104121 result = result . replace ( CHAIN_OF_THOUGHT_BLOCK_RE , '' ) . replace ( CHAIN_OF_THOUGHT_TAG_RE , '' ) ;
105122 }
106123
124+ // Strip leaked code blocks when artifacts are present — code content
125+ // should only appear inside artifact actions, never in chat text
126+ if ( result . includes ( '__devonzArtifact__' ) ) {
127+ result = result . replace ( LEAKED_CODE_BLOCK_RE , '' ) ;
128+ result = result . replace ( UNCLOSED_CODE_BLOCK_RE , '' ) ;
129+ }
130+
107131 return result ;
108132}
109133
0 commit comments