diff --git a/src/app.ts b/src/app.ts index a489859..49b19b4 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,6 +2,7 @@ import Fastify from 'fastify'; import { addPages, getScan, addProperties, addReports, addResults, addScans, deleteProperties, deleteReports, deleteUser, getApikey, getCharts, getFilters, getProperties, getReports, getResultsAll, getResultsMessages, getResultsSchema, getResultsTags, getResultsUrls, getScans, getUpdates, help, trackUser, updateProperties, updateReports, getPages } from '#src/routes'; import { CognitoJwtVerifier } from 'aws-jwt-verify'; import { db } from './utils'; +import { suggestIssue } from './routes/suggestIssue'; export const fastify = Fastify(); const cognitoJwtVerifier = CognitoJwtVerifier.create({ @@ -67,6 +68,7 @@ fastify.delete('/delete/user', {}, async (request, reply) => deleteUser({ reques // MISC requests fastify.post('/help', {}, async (request, reply) => help({ request, reply })); fastify.post('/track/user', {}, async (request, reply) => trackUser({ request, reply })); +fastify.post('/ai/suggest-issue', {}, async (request, reply) => suggestIssue({ request, reply })); fastify.listen({ port: 3000 }, (err) => { console.log(`Server listening on ${fastify.server.address().port}`) diff --git a/src/routes/index.ts b/src/routes/index.ts index a0270ab..d5f1a96 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -25,4 +25,5 @@ export * from './deleteUser' export * from './trackUser' export * from './addPages' export * from './getPages' -export * from './getScan' \ No newline at end of file +export * from './getScan' +export * from './suggestIssue' \ No newline at end of file diff --git a/src/routes/suggestIssue.ts b/src/routes/suggestIssue.ts new file mode 100644 index 0000000..b5a1cda --- /dev/null +++ b/src/routes/suggestIssue.ts @@ -0,0 +1,56 @@ +import { stripHtml } from 'string-strip-html'; +import { openai } from '#src/utils'; + +export const suggestIssue = async ({ request, reply }) => { + const { reportId, messageId, dequeUrl, messageName: accessibilityIssueToFix, codeSnippet: originalCodeSnippet, pageUrl } = request.body; + const accessibilityDocumentation = stripHtml(await (await fetch(dequeUrl)).text()).result; + const originalCode = await (await fetch(pageUrl)).text(); + + const openaiRawResponse = await openai.chat.completions.create({ + model: 'gpt-4-turbo-preview', + tool_choice: { type: 'function', function: { name: 'suggested_fix' } }, + tools: [{ + type: 'function', + function: { + name: 'suggested_fix', + description: 'Suggest an accessibility fix for the given code snippet and accessibility rule', + parameters: { + type: 'object', + description: 'A suggested fix', + properties: { + suggested_replacement_code: { + type: 'string', + description: 'The suggested replacement code', + }, + how_to_implement: { + type: 'string', + description: 'How to implement the suggested code', + }, + }, + required: ['suggested_replacement_code', 'how_to_implement'], + }, + } + }], + messages: [ + { role: 'system', content: `You are an LLM bot running for Equalify, a platform designed to identify accessibility issues for developers to fix.` }, + { + role: 'user', content: `Suggest replacement code to fix the accessibility issue identified by Equalify. You may use the accessibility documentation to assist in your resolution: + \`\`\`json + ${JSON.stringify({ + originalCode, + originalCodeSnippet, + accessibilityIssueToFix, + accessibilityDocumentation, + })} + \`\`\` + `}, + ] + }); + + const suggestedFix = JSON.parse(openaiRawResponse.choices?.[0]?.message?.tool_calls?.[0]?.function?.arguments ?? '{}'); + + return { + ...suggestedFix, + originalCode, + }; +} \ No newline at end of file