Skip to content

Commit bfb6878

Browse files
Merge branch 'main' into fix/dark-theme-gauge-and-sort-widgets
2 parents 8e79c50 + 468e920 commit bfb6878

3 files changed

Lines changed: 62 additions & 6 deletions

File tree

backend/src/entities/ai/use-cases/request-info-from-table-with-ai-v3.use.case.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { isConnectionTypeAgent } from '../../../helpers/is-connection-entity-age
1111
import { IRequestInfoFromTableV2 } from '../ai-use-cases.interface.js';
1212
import { RequestInfoFromTableDSV2 } from '../application/data-structures/request-info-from-table.ds.js';
1313
import { getOpenAiTools } from './use-cases-utils/get-open-ai-tools.util.js';
14+
import Sentry from '@sentry/minimal';
15+
import { slackPostMessage } from '../../../helpers/index.js';
1416

1517
declare module 'express-session' {
1618
interface Session {
@@ -60,11 +62,13 @@ export class RequestInfoFromTableWithAIUseCaseV3
6062

6163
await this.processStream(stream, response, dao, tableName, userEmail, foundConnection, isMongoDb, user_message);
6264
} catch (streamError) {
65+
Sentry.captureException(streamError);
6366
this.handleStreamError(streamError, response);
6467
}
6568

6669
this.cleanupAndEnd(heartbeatInterval, response);
6770
} catch (error) {
71+
Sentry.captureException(error);
6872
this.handleError(response, error, 'AI request processing');
6973
this.cleanupAndEnd(heartbeatInterval, response);
7074
}
@@ -280,6 +284,7 @@ Remember that all responses should be clear and user-friendly, explaining techni
280284
);
281285
}
282286
} catch (error) {
287+
Sentry.captureException(error);
283288
this.handleError(response, error, 'processing your request');
284289
}
285290
}
@@ -334,10 +339,9 @@ Remember that all responses should be clear and user-friendly, explaining techni
334339
aiResponseBuffer,
335340
);
336341
} catch (innerStreamError) {
342+
Sentry.captureException(innerStreamError);
337343
console.error('Error creating second OpenAI stream with table structure data:', innerStreamError);
338-
response.write(
339-
`Sorry, I encountered a problem analyzing your table information: ${innerStreamError.message}`,
340-
);
344+
response.write(`Sorry, I encountered a problem analyzing your table information: ${innerStreamError.message}`);
341345
}
342346
}
343347

@@ -465,9 +469,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
465469
response.write(`Sorry, I'm having trouble connecting to the AI service: ${streamError.message}`);
466470

467471
if (streamError.status === 401) {
468-
response.write(
469-
`This may be due to insufficient API permissions. Please check your API key configuration.`,
470-
);
472+
response.write(`This may be due to insufficient API permissions. Please check your API key configuration.`);
471473
} else if (streamError.status === 500) {
472474
response.write(`This appears to be a temporary issue with the AI service. Please try again later.`);
473475
}
@@ -637,6 +639,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
637639
JSON.parse(possibleJson);
638640
return possibleJson;
639641
} catch (_parseErr) {
642+
Sentry.captureException(_parseErr);
640643
console.error('Could not sanitize JSON, returning empty object');
641644
return '{}';
642645
}
@@ -716,6 +719,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
716719
}
717720
}
718721
} catch (error) {
722+
Sentry.captureException(error);
719723
console.error('Error executing SQL query:', error);
720724
response.write(`Sorry, I couldn't retrieve the data you requested: ${error.message}`);
721725
}
@@ -767,6 +771,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
767771
}
768772
}
769773
} catch (error) {
774+
Sentry.captureException(error);
770775
console.error('Error executing MongoDB pipeline:', error);
771776
response.write(`Sorry, I couldn't complete the data analysis you requested: ${error.message}`);
772777
}
@@ -777,6 +782,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
777782
response.write(`Received unknown tool call: ${toolName}`);
778783
}
779784
} catch (error) {
785+
Sentry.captureException(error);
780786
this.handleError(response, error, 'in processQueryToolCall');
781787
}
782788
}
@@ -798,6 +804,7 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
798804
const sample = results.slice(0, 5);
799805
return `${JSON.stringify(sample, null, 2)}\n\n(Showing 5 of ${results.length} results)`;
800806
} catch (error) {
807+
Sentry.captureException(error);
801808
console.error('Error formatting query results:', error);
802809
return JSON.stringify(results);
803810
}
@@ -861,11 +868,13 @@ Remember: You MUST use the executeRawSql tool to run your query and show me the
861868

862869
return true;
863870
} catch (error) {
871+
Sentry.captureException(error);
864872
console.error('Error auto-executing detected SQL query:', error);
865873
response.write(`Sorry, I couldn't retrieve that data for you: ${error.message}`);
866874
return true;
867875
}
868876
} catch (error) {
877+
Sentry.captureException(error);
869878
console.error('Error in detectAndExecuteSqlQueries:', error);
870879
return false;
871880
}
@@ -934,7 +943,11 @@ Please provide a clear, concise, and conversational answer that directly address
934943
console.log('No content returned from responses API, falling back to completions');
935944
}
936945
} catch (responsesError) {
946+
Sentry.captureException(responsesError);
937947
console.error('Error using responses API:', responsesError);
948+
await slackPostMessage(
949+
`Error using responses API for query: ${query}\nError details: ${responsesError.message}`,
950+
);
938951
if (responsesError instanceof Error) {
939952
console.error('Responses API error details:', responsesError.message);
940953
console.error('Responses API error stack:', responsesError.stack);
@@ -974,6 +987,7 @@ Please provide a clear, concise, and conversational answer that directly address
974987
return fallbackMessage;
975988
}
976989
} catch (error) {
990+
Sentry.captureException(error);
977991
console.error('Error generating human-readable answer:', error);
978992
return `There are ${this.extractResultCount(queryResult)} records in the results.`;
979993
}
@@ -993,6 +1007,7 @@ Please provide a clear, concise, and conversational answer that directly address
9931007

9941008
return results;
9951009
} catch (error) {
1010+
Sentry.captureException(error);
9961011
console.error('Error getting first result:', error);
9971012
return null;
9981013
}
@@ -1012,6 +1027,7 @@ Please provide a clear, concise, and conversational answer that directly address
10121027

10131028
return [results];
10141029
} catch (error) {
1030+
Sentry.captureException(error);
10151031
console.error('Error getting sample results:', error);
10161032
return [];
10171033
}
@@ -1053,6 +1069,7 @@ Please provide a clear, concise, and conversational answer that directly address
10531069
return false;
10541070
}
10551071
} catch (error) {
1072+
Sentry.captureException(error);
10561073
console.error('Error in streamHumanReadableAnswer:', error);
10571074
return false;
10581075
}
@@ -1248,6 +1265,7 @@ Please provide a clear, concise, and conversational answer that directly address
12481265
simplifiedResult.sample = JSON.parse(JSON.stringify(sampleRows));
12491266
}
12501267
} catch (innerError) {
1268+
Sentry.captureException(innerError);
12511269
console.error('Error processing row data:', innerError);
12521270
simplifiedResult['sample'] = results.rows.slice(0, 10).map((row) =>
12531271
Object.keys(row).reduce((acc, key) => {
@@ -1271,6 +1289,7 @@ Please provide a clear, concise, and conversational answer that directly address
12711289
sample: JSON.parse(JSON.stringify(results.slice(0, 10))),
12721290
};
12731291
} catch (jsonError) {
1292+
Sentry.captureException(jsonError);
12741293
console.error('Error stringifying array results:', jsonError);
12751294
return {
12761295
type: 'array',
@@ -1289,6 +1308,8 @@ Please provide a clear, concise, and conversational answer that directly address
12891308
return String(item);
12901309
}
12911310
} catch (_e) {
1311+
console.error('Error processing array item:', _e);
1312+
Sentry.captureException(_e);
12921313
return '[Complex Object]';
12931314
}
12941315
}),
@@ -1313,6 +1334,7 @@ Please provide a clear, concise, and conversational answer that directly address
13131334
simplifiedResult.sample = JSON.parse(JSON.stringify(results.rows.slice(0, 10)));
13141335
}
13151336
} catch (jsonError) {
1337+
Sentry.captureException(jsonError);
13161338
console.error('Error processing fieldset data:', jsonError);
13171339
if (Array.isArray(results.fields)) {
13181340
simplifiedResult.fields = results.fields.map((f) => String(f.name || f));
@@ -1345,6 +1367,7 @@ Please provide a clear, concise, and conversational answer that directly address
13451367
}),
13461368
);
13471369
} catch (finalError) {
1370+
Sentry.captureException(finalError);
13481371
console.error('Error serializing results:', finalError);
13491372
return {
13501373
type: 'unserializable',
@@ -1353,6 +1376,7 @@ Please provide a clear, concise, and conversational answer that directly address
13531376
};
13541377
}
13551378
} catch (error) {
1379+
Sentry.captureException(error);
13561380
console.error('Error simplifying query results:', error);
13571381
return {
13581382
type: 'error',
@@ -1389,6 +1413,7 @@ Please provide a clear, concise, and conversational answer that directly address
13891413

13901414
return 0;
13911415
} catch (error) {
1416+
Sentry.captureException(error);
13921417
console.error('Error extracting result count:', error);
13931418
return 0;
13941419
}
@@ -1407,6 +1432,7 @@ Please provide a clear, concise, and conversational answer that directly address
14071432
try {
14081433
return JSON.stringify(value);
14091434
} catch (error) {
1435+
Sentry.captureException(error);
14101436
console.error('Error stringifying object:', error);
14111437
return '[Complex Object]';
14121438
}
@@ -1444,6 +1470,7 @@ Please provide a clear, concise, and conversational answer that directly address
14441470

14451471
return totalLength;
14461472
} catch (error) {
1473+
Sentry.captureException(error);
14471474
console.error('Error calculating content length:', error);
14481475
return 0;
14491476
}
@@ -1511,6 +1538,7 @@ Please provide a clear, concise, and conversational answer that directly address
15111538
currentToolCall.function.arguments += typedChunk.delta;
15121539
}
15131540
} catch (error) {
1541+
Sentry.captureException(error);
15141542
console.error('Error processing function call arguments delta:', error);
15151543
}
15161544
return currentToolCall;

backend/src/entities/table-filters/use-cases/update-table-filters.use.case.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ export class UpdateTableFiltersUseCase
5353
}
5454

5555
const updatedFilterEntity = buildNewTableFiltersEntity(updatedTableFilterData);
56+
for (const key in updatedFilterEntity) {
57+
// eslint-disable-next-line security/detect-object-injection
58+
if (updatedFilterEntity[key] === undefined) {
59+
// eslint-disable-next-line security/detect-object-injection
60+
delete updatedFilterEntity[key];
61+
}
62+
}
5663
const updatedFilters = Object.assign(filtersToUpdate, updatedFilterEntity);
5764
await this._dbContext.tableFiltersRepository.save(updatedFilters);
5865
return buildCreatedTableFilterRO(updatedFilters);

backend/test/ava-tests/saas-tests/table-filters-e2e-test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,28 @@ test.serial(`${currentTest} should return updated table filters`, async (t) => {
287287
t.is(updateTableFiltersRO.hasOwnProperty('createdAt'), true);
288288
t.is(updateTableFiltersRO.hasOwnProperty('updatedAt'), true);
289289
t.is(updateTableFiltersRO.name, updatedFiltersDTO.name);
290+
t.is(updateTableFiltersRO.id, createTableFiltersRO.id);
290291
t.deepEqual(updateTableFiltersRO.filters, updatedFiltersDTO.filters);
292+
293+
// should return updated table filters
294+
const getUpdatedTableFiltersResponse = await request(app.getHttpServer())
295+
.get(`/table-filters/${createConnectionRO.id}/all/?tableName=${testTableName}`)
296+
.set('Cookie', firstUserToken)
297+
.set('Content-Type', 'application/json')
298+
.set('Accept', 'application/json');
299+
const getUpdatedTableFiltersRO = JSON.parse(getUpdatedTableFiltersResponse.text);
300+
t.is(Array.isArray(getUpdatedTableFiltersRO), true);
301+
t.is(getUpdatedTableFiltersRO.length, 1);
302+
getUpdatedTableFiltersRO.forEach((el) => {
303+
t.is(el.hasOwnProperty('id'), true);
304+
t.is(el.hasOwnProperty('name'), true);
305+
t.is(el.hasOwnProperty('filters'), true);
306+
t.is(el.hasOwnProperty('dynamic_column'), true);
307+
t.is(el.hasOwnProperty('createdAt'), true);
308+
t.is(el.hasOwnProperty('updatedAt'), true);
309+
t.is(el.name, updatedFiltersDTO.name);
310+
t.deepEqual(el.filters, updatedFiltersDTO.filters);
311+
});
291312
} catch (e) {
292313
console.error(e);
293314
t.fail();

0 commit comments

Comments
 (0)