@@ -12,22 +12,35 @@ export interface SearchChatCitation {
1212const CARD_TAGS = 'options|question|usage_upgrade|credential|workspace_resource'
1313/** A JSON string owns its escaped quotes and any tag-shaped text inside it. */
1414const JSON_STRING = '"(?:\\\\.|[^"\\\\\\r\\n])*"'
15- /**
16- * A card whose body is a JSON value, a thinking block, or a card opener left unclosed before a
17- * JSON payload. A tag-shaped pair or opener in ordinary prose is not a card and stays.
18- */
19- const INTERACTIVE_CARD = new RegExp (
20- [
21- `<(${ CARD_TAGS } )>\\s*[[{](?:${ JSON_STRING } |[^"<])*?[\\]}]\\s*</\\1>` ,
22- '<thinking>[\\s\\S]*?</thinking>' ,
23- `<(?:${ CARD_TAGS } )>\\s*[[{][\\s\\S]*$` ,
24- ] . join ( '|' ) ,
15+ /** A closed card candidate; its body is removed only when it parses as a JSON payload. */
16+ const CLOSED_CARD = new RegExp (
17+ `<(${ CARD_TAGS } )>(\\s*[[{](?:${ JSON_STRING } |[^"<])*?[\\]}]\\s*)</\\1>` ,
2518 'g'
2619)
20+ /** A card the model left open, followed by the start of a JSON object with a quoted key. */
21+ const UNCLOSED_CARD = new RegExp (
22+ `<(${ CARD_TAGS } )>(?![\\s\\S]*</\\1>)\\s*(?:\\{\\s*"|\\[\\s*[{"])[\\s\\S]*$`
23+ )
24+ const THINKING = / < t h i n k i n g > [ \s \S ] * ?< \/ t h i n k i n g > / g
25+
26+ function isJsonPayload ( body : string ) : boolean {
27+ try {
28+ const value : unknown = JSON . parse ( body )
29+ return typeof value === 'object' && value !== null
30+ } catch {
31+ return false
32+ }
33+ }
2734
28- /** Removes interactive Chat cards so a text-only surface receives only the answer prose. */
35+ /**
36+ * Removes interactive Chat cards so a text-only surface receives only the answer prose. A tag
37+ * pair whose body is not a JSON payload is prose that happens to look like a card, and stays.
38+ */
2939export function stripInteractiveCards ( content : string ) : string {
30- return content . replace ( INTERACTIVE_CARD , '' )
40+ return content
41+ . replace ( CLOSED_CARD , ( card , _tag : string , body : string ) => ( isJsonPayload ( body ) ? '' : card ) )
42+ . replace ( THINKING , '' )
43+ . replace ( UNCLOSED_CARD , '' )
3144}
3245
3346/** Resolves Assistant source tags only against successful, bounded retrieval evidence. */
0 commit comments