@@ -80,27 +80,30 @@ export function AskAIResults({
80
80
81
81
const [ conversationId , setConversationId ] = useState < string > ( '' )
82
82
83
- const handleAICannotAnswer = ( passedConversationId ?: string ) => {
83
+ const handleAICannotAnswer = (
84
+ passedConversationId ?: string ,
85
+ statusCode = 400 ,
86
+ uiMessage = t ( 'search.ai.responses.unable_to_answer' ) ,
87
+ ) => {
84
88
setInitialLoading ( false )
85
89
setResponseLoading ( false )
86
90
setAICouldNotAnswer ( true )
87
- const cannedResponse = t ( 'search.ai.unable_to_answer' )
88
91
sendAISearchResultEvent ( {
89
92
sources : [ ] ,
90
- message : cannedResponse ,
93
+ message : uiMessage ,
91
94
eventGroupId : askAIEventGroupId . current ,
92
95
couldNotAnswer : true ,
93
- status : 400 ,
96
+ status : statusCode ,
94
97
connectedEventId : passedConversationId || conversationId ,
95
98
} )
96
- setMessage ( cannedResponse )
97
- setAnnouncement ( cannedResponse )
99
+ setMessage ( uiMessage )
100
+ setAnnouncement ( uiMessage )
98
101
setReferences ( [ ] )
99
102
setItem (
100
103
query ,
101
104
{
102
105
query,
103
- message : cannedResponse ,
106
+ message : uiMessage ,
104
107
sources : [ ] ,
105
108
aiCouldNotAnswer : true ,
106
109
connectedEventId : passedConversationId || conversationId ,
@@ -158,17 +161,44 @@ export function AskAIResults({
158
161
try {
159
162
const response = await executeAISearch ( router , version , query , debug )
160
163
if ( ! response . ok ) {
161
- console . error (
162
- `Failed to fetch search results.\nStatus ${ response . status } \n${ response . statusText } ` ,
163
- )
164
- sendAISearchResultEvent ( {
165
- sources : [ ] ,
166
- message : '' ,
167
- eventGroupId : askAIEventGroupId . current ,
168
- couldNotAnswer : false ,
169
- status : response . status ,
170
- } )
171
- return setAISearchError ( )
164
+ // If there is JSON and the `upstreamStatus` key, the error is from the upstream sever (CSE)
165
+ let responseJson
166
+ try {
167
+ responseJson = await response . json ( )
168
+ } catch ( error ) {
169
+ console . error ( 'Failed to parse JSON:' , error )
170
+ }
171
+ const upstreamStatus = responseJson ?. upstreamStatus
172
+ // If there is no upstream status, the error is either on our end or a 500 from CSE, so we can show the error
173
+ if ( ! upstreamStatus ) {
174
+ console . error (
175
+ `Failed to fetch search results.\nStatus ${ response . status } \n${ response . statusText } ` ,
176
+ )
177
+ sendAISearchResultEvent ( {
178
+ sources : [ ] ,
179
+ message : '' ,
180
+ eventGroupId : askAIEventGroupId . current ,
181
+ couldNotAnswer : false ,
182
+ status : response . status ,
183
+ } )
184
+ return setAISearchError ( )
185
+ // Query invalid - either sensitive question or spam
186
+ } else if ( upstreamStatus === 400 || upstreamStatus === 422 ) {
187
+ return handleAICannotAnswer ( '' , upstreamStatus , t ( 'search.ai.responses.invalid_query' ) )
188
+ // Query too large
189
+ } else if ( upstreamStatus === 413 ) {
190
+ return handleAICannotAnswer (
191
+ '' ,
192
+ upstreamStatus ,
193
+ t ( 'search.ai.responses.query_too_large' ) ,
194
+ )
195
+ } else if ( upstreamStatus === 429 ) {
196
+ return handleAICannotAnswer (
197
+ '' ,
198
+ upstreamStatus ,
199
+ t ( 'search.ai.responses.asked_too_many_times' ) ,
200
+ )
201
+ }
172
202
} else {
173
203
setAISearchError ( false )
174
204
}
@@ -211,7 +241,7 @@ export function AskAIResults({
211
241
return
212
242
}
213
243
} catch ( e ) {
214
- console . error (
244
+ console . warn (
215
245
'Failed to parse JSON:' ,
216
246
e ,
217
247
'Line:' ,
@@ -228,7 +258,7 @@ export function AskAIResults({
228
258
setConversationId ( parsedLine . conversation_id )
229
259
} else if ( parsedLine . chunkType === 'NO_CONTENT_SIGNAL' ) {
230
260
// Serve canned response. A question that cannot be answered was asked
231
- handleAICannotAnswer ( conversationIdBuffer )
261
+ handleAICannotAnswer ( conversationIdBuffer , 200 )
232
262
} else if ( parsedLine . chunkType === 'SOURCES' ) {
233
263
if ( ! isCancelled ) {
234
264
sourcesBuffer = sourcesBuffer . concat ( parsedLine . sources )
@@ -242,7 +272,11 @@ export function AskAIResults({
242
272
}
243
273
} else if ( parsedLine . chunkType === 'INPUT_CONTENT_FILTER' ) {
244
274
// Serve canned response. A spam question was asked
245
- handleAICannotAnswer ( conversationIdBuffer )
275
+ handleAICannotAnswer (
276
+ conversationIdBuffer ,
277
+ 200 ,
278
+ t ( 'search.ai.responses.invalid_query' ) ,
279
+ )
246
280
}
247
281
if ( ! isCancelled ) {
248
282
setAnnouncement ( 'Copilot Response Loading...' )
0 commit comments