@@ -47,6 +47,48 @@ function stripMarkdownCode(text) {
4747 . replace ( / ` [ ^ ` \n ] * ` / g, ' ' ) ;
4848}
4949
50+ /**
51+ * @summary Replaces quoted prose spans that report a phrase instead of using it.
52+ * @param {String } text Assistant final-turn text with code spans already removed.
53+ * @returns {String }
54+ */
55+ function stripQuotedMentions ( text ) {
56+ return text
57+ . replace ( / " [ ^ " \n ] * " / g, ' ' )
58+ . replace ( / ( ^ | [ ^ a - z A - Z 0 - 9 _ ] ) ' [ ^ ' \n ] * ' (? = $ | [ ^ a - z A - Z 0 - 9 _ ] ) / g, '$1 ' ) ;
59+ }
60+
61+ /**
62+ * @summary Checks whether a local match is a reported phrase rather than deference.
63+ * @param {String } text Searchable assistant final-turn text.
64+ * @param {Number } startIndex Match start index.
65+ * @returns {Boolean }
66+ */
67+ function isReportedMentionContext ( text , startIndex ) {
68+ const prefix = text . slice ( Math . max ( 0 , startIndex - 80 ) , startIndex ) . toLowerCase ( ) ;
69+
70+ return / \b (?: t h e | t h i s | t h a t ) \s + (?: l i t e r a l \s + ) ? (?: p h r a s e | t e x t | s t r i n g | t r i g g e r | m a t c h e d \s + t e x t | w o r d i n g ) \s * $ / . test ( prefix ) ||
71+ / \b (?: q u o t e d | r e p o r t e d | m e n t i o n (?: e d | i n g ) ? | d o c u m e n t (?: e d | i n g ) ? ) \s * $ / . test ( prefix ) ;
72+ }
73+
74+ /**
75+ * @summary Checks whether a local "your call" match cites a prior operator decision.
76+ * @param {String } phrase Matched deference phrase.
77+ * @param {String } text Searchable assistant final-turn text.
78+ * @param {Number } startIndex Match start index.
79+ * @returns {Boolean }
80+ */
81+ function isAttributiveCitationContext ( phrase , text , startIndex ) {
82+ if ( phrase . toLowerCase ( ) !== 'your call' ) {
83+ return false ;
84+ }
85+
86+ const prefix = text . slice ( Math . max ( 0 , startIndex - 80 ) , startIndex ) . toLowerCase ( ) ;
87+
88+ return / \b p e r \s + $ / . test ( prefix ) ||
89+ / \b a s \s + y o u \s + (?: s a i d | d i r e c t e d | c a l l e d ) \W * $ / . test ( prefix ) ;
90+ }
91+
5092/**
5193 * @summary Returns the first deference phrase found in text, using case-insensitive boundary match.
5294 * @param {String } text Assistant final-turn text.
@@ -58,13 +100,23 @@ export function matchDeferencePhrase(text = '', phrases = DEFERENCE_PHRASES) {
58100 return null ;
59101 }
60102
61- const searchableText = stripMarkdownCode ( text ) ;
103+ const searchableText = stripQuotedMentions ( stripMarkdownCode ( text ) ) ;
62104
63105 return phrases . find ( phrase => {
64106 const escaped = phrase . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) . replace ( / \s + / g, '\\s+' ) ,
65- matcher = new RegExp ( `(^|[^a-z0-9_])${ escaped } (?=$|[^a-z0-9_])` , 'i' ) ;
107+ matcher = new RegExp ( `(^|[^a-z0-9_])${ escaped } (?=$|[^a-z0-9_])` , 'ig' ) ;
108+ let match ;
109+
110+ while ( ( match = matcher . exec ( searchableText ) ) !== null ) {
111+ const startIndex = match . index + match [ 1 ] . length ;
112+
113+ if ( ! isReportedMentionContext ( searchableText , startIndex ) &&
114+ ! isAttributiveCitationContext ( phrase , searchableText , startIndex ) ) {
115+ return true ;
116+ }
117+ }
66118
67- return matcher . test ( searchableText ) ;
119+ return false ;
68120 } ) || null ;
69121}
70122
0 commit comments